Tutorial: Dynamic Svelte Components

Saturday, December 14, 2024 · 3 minutes · 483 words

Svelte offers remarkable flexibility for creating dynamic components. In this tutorial, we’ll explore how to instantiate components on the fly and pass properties to them in an elegant and efficient manner.

Basics of Dynamic Components

<script>
  import Foo from "./Foo.svelte";
  import Bar from "./Bar.svelte";
  let actual = Foo;
</script>

<svelte:component this={actual} on:click={()=>actual=Bar} />

In this simple example, we import two components: Foo and Bar.

We create a variable actual where we’ll place the current component, in this case Foo.

Svelte offers a special <svelte:component> tag that allows creating components on the fly.

We specify in the this property which component to display, in our example, actual.

For demonstration, we add an on:click event to change the component to Bar by simply modifying the actual variable.

Svelte takes care of displaying the component by substituting Bar for Foo.

Passing Parameters (props)

A key point is the ability to pass parameters to dynamic components. For a classic component, you can write:

<Foo age=22 />

We assign the value 22 to the age property.

For a dynamic component, it’s the same:

<svelte:component this={Foo} age=22 />

But let’s imagine our second component Bar accepts 2 parameters:

<Bar age=572 name="Da Vinci" />

Our dynamic component should be written as:

<svelte:component this={Bar} age=572 name="Da Vinci" />

And there, we have a problem. How to manage them in the dynamic component while passing the right number of parameters?

My technique involves encapsulating the component with its properties in an object and using the spread operator {...props}.

For example, for the Foo component, I would write an object FooCmp:

<script>
    let FooCmp = {
        cmp: Foo,
        props: {
            age: 42
        }
    }
    let actual = FooCmp;
</script>

<svelte:component
    this={actual.cmp}
    {...actual.props}
/>

Here’s the complete example, using the 2 components and a flip function to interchange them.

App.svelte

<script>
  import Foo from "./Foo.svelte";
  import Bar from "./Bar.svelte";
  let FooCmp = {
    cmp: Foo,
    props: {
      age: 42
    }
  };
  let BarCmp = {
    cmp: Bar,
    props: {
      age: 572,
      name: "Da Vinci"
    }
  };
  let actual = FooCmp;
  let flip = () => actual = actual.cmp == Foo ? BarCmp : FooCmp;
</script>

<svelte:component
    this={actual.cmp}
    on:click={flip}
    {...actual.props}
/>

Each imported component will display its properties in a button and activate the on:click event.

Foo.svelte

<script>
    export let age = 0;
</script>

<button on:click>Foo {age}</button>

Bar.svelte

<script>
    export let name = "";
    export let age = 0;
</script>

<button on:click>Bar {name} {age}</button>

Note that we only pass through the on:click event as it is not processed here, but at the level of the parent, the dynamic component.

Conclusion

You can easily instantiate and manipulate components on the fly with <svelte:component>. Svelte offers a simple and powerful approach to creating dynamic components.

And JavaScript provides us with all the tools to work around the problem of different numbers of props per component.

Don’t hesitate to experiment and adapt this approach to your own needs!

tutorial svelte