Composing Svelte Components with Slots
Tags: svelte, webdev, programming, javascript
Published: 2021-01-28 21:38:20

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Svelte is an up and coming front end framework for developing front end web apps.

It’s simple to use and lets us create results fast.

In this article, we’ll look at how to nest Svelte components with slots.

### Component Composition

We can add the `slot` component to a Svelte component to let us nest components inside another component.

For example, we can use the `slot` component as follows:

`App.svelte` :

```
<script>
import Parent from "./Parent.svelte";
import Foo from "./Foo.svelte";
</script>

<Parent>
  <Foo />
</Parent>
```

`Parent.svelte` :

```
<div>
  <p>Start</p>
  <p>
    <slot></slot>
  </p>
  <p>End</p>
</div>
```

`Foo.svelte` :

```
<button>
  foo
</button>
```

In the code above, we have the `Parent` component, which has the `slot` component, which lets us nest one or more components inside it.

`Parent` has 3 p elements. The `slot` is in the 2nd p element.

We created the `Foo` component with a button. Then when we write:

```
<Parent>
  <Foo />
</Parent>
```

in `App.svelte` , we’ll see the button displayed between ‘start’ and ‘end’.

### Fallback Content

We can put fallback content in between the `slot` tags so that when we didn’t pass in anything in between the tags of the component with the `slot` component, then we’ll still see something displayed.

For example, we can write the following code to add fallback content and display it:

`App.svelte` :

```
<script>
import Parent from "./Parent.svelte";
</script>

<Parent />
```

`Parent.svelte` :

```
<div>
  <p>Start</p>
  <p>
    <slot>
      <p>Nothing to see here</p>
    </slot>
  </p>
  <p>End</p>
</div>
```

In the code above, we have:

```
<p>Nothing to see here</p>
```

in between the `slot` tags. Then when we write `<Parent />` as we did in `App.svelte` , we’ll see:

```
Start

Nothing to see here

End
```

displayed on the screen since we used a self-closing version of `Parent` instead of passing child elements in between the tags.

### Multiple Slots with Named Slots

We can add multiple slots by naming the slots. Then we can add content for each slot with the `slot` attribute with the name of the slot as the value.

For instance, we can write the following code to add multiple slots and populate them with content:

`Contact.svelte` :

```
<article>
  <h2>
    <slot name="name">
      <span>No name</span>
    </slot>
  </h2>

  <div class="address">
    <slot name="address">
      <span>No address</span>
    </slot>
  </div>

  <div class="email">
    <slot name="email">
      <span>No email</span>
    </slot>
  </div>
</article>
```

`App.svelte`

```
<script>
import Contact from "./Contact.svelte";
</script>

<Contact>
  <span slot="name">
    Jane Smith
  </span>

  <span slot="address">
    123 A St.
  </span>

  <span slot="email">
    abc@abc.com
  </span>
</Contact>
```

In the code above, we defined multiple slots with the `name` attribute added to each in `Contact.svelte` .

Then we can use the `Contact` component in `App.svelte` when we pass in components into each slot as identified by their names. Therefore, we should see:

```
Jane Smith

123 A St.
abc@abc.com
```

displayed on the screen.

### Passing Child Data to Parent Component via Slots

We can use slot props to pass data from the child component to the parent component. To define slot props, we set the prop name with the variable that we want to pass to the parent as the value.

To define slot props and use it, we can write the following code:

`Contact.svelte` :

```
<script>
let names = ["John", "Jane", "Mary"];
</script>

<article>
  <slot names={names}></slot>
</article>
```

The code above has the slot prop `names` , which we pass the `names` variable into it.

Then we can use it in `App.svelte` as follows:

```
<script>
import Contact from "./Contact.svelte";
</script>

<Contact let:names={names}>
  {#each names as name}
    <p>{name}</p>
  {/each}
</Contact>
```

The `let` directive defines the slot prop variable, which should have the slot prop as the value.

In the code above, `let:names={names}` sets the slot props with the `names` prop from `Contact` as the value for the `names` variable in `App.svelte` .

Then we can access `names` inside the loop as we did in the `each` loop.

Therefore, we should get:

```
John

Jane

Mary
```

displayed on the screen.

Named slots can also have props. We can write:

`Contact.svelte` :

```
<script>
let contactName = "Jane Smith";
let address = "123 A. St";
let email = "abc@abc.com";
</script>

<article>
  <h2>
    <slot name="name" contactName={contactName}>
      <span>No name</span>
    </slot>
  </h2>
  <div class="address">
    <slot name="address" address={address}>
      <span>No address</span>
    </slot>
  </div>
  <div class="email">
    <slot name="email" email={email}>
      <span>No email</span>
    </slot>
  </div>
</article>
```

`App.svelte` :

```
<script>
import Contact from "./Contact.svelte";
</script>

<Contact>
  <span slot="name" let:contactName={contactName}>
    {contactName}
  </span>
  <span slot="address" let:address={address}>
    {address}
  </span>
  <span slot="email" let:email={email}>
    {email}
  </span>
</Contact>
```

In the code above, we defined slot props for each slot, and then pass them into the `App.svelte` component with the `let` directive as we did with the single slot example.

Therefore, we should have:

```
Jane Smith

123 A St.
abc@abc.com
```

displayed as we did with the earlier example.

### Conclusion

We can use slots to nest components within another component. To pass data from the child components to the parent, we can use slot props.

Slot props are defined with the `let` directive. The value of it should be the variable name to reference the slot prop value. Then we can access the slot prop value in between the tags.

Fallback content can be added between the `slot` tags and they’re displayed and we reference a component with a self-closing tag.