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.