Composition in Svelte 3: slots
Oleksandr Demian
Posted on March 21, 2020
Table Of Contents
Composition is a powerful tool that allows you to create complex application functionality by combining small and easily manageable components. To achieve composition in Svelte 3, you have to use a slot directive.
Slots
As a normal html element, a svelte 3 component can have some child content.You can pass any valid html data inside a component, and it will be rendered inside a slot directive:
Box.svelte
<style>
.box {
width: 250px;
border: 1px solid #aaa;
padding: 1em;
margin: 1em;
display: inline-block;
}
</style>
<div class="box">
<slot></slot>
</div>
<script>
import Box from "./Box.svelte";
</script>
<Box>
<h1>Hello World</h1>
<p>Some paragraf</p>
</Box>
As the result you will have a box with a header and paragraph inside of a box.
Slot fallback
Slot allows you to define some custom content that will be shown if there is no child content:
SlotWithFallback.svelte
<slot>
<h2>There is no child content!</h2>
</slot>
App.svelte
<script>
import SlotWithFallback from "./SlotWithFallback.svelte";
</script>
<!-- will render h1 and p -->
<SlotWithFallback>
<h1>Hello World</h1>
<p>Some paragraf</p>
</SlotWithFallback>
<!-- will render <h2>There is no child content!</h2> -->
<SlotWithFallback />
Named slots
Sometimes you will need to target different slots inside the same component. You can do this by adding names to slots:
NamedBox.svelte
<style>
.box {
width: 250px;
border: 1px solid #aaa;
padding: 1em;
margin: 1em;
display: inline-block;
}
</style>
<div class="box">
<slot name="top"></slot>
<hr />
<slot name="bottom"></slot>
</div>
App.svelte
<script>
import NamedBox from "./NamedBox.svelte";
</script>
<!-- will render h1 in top slot and p in bottom slot -->
<NamedBox>
<h1 slot="top">Title</h1>
<p slot="bottom">Paragraph</p>
</NamedBox>
Slot props
In Svelte 3 you can also reference variables of parent component. Let's create a box with a secret content that can be toggled using checkbox:
Secret.svelte
<script>
let showSecret = false;
</script>
<label>
<input type="checkbox" bind:checked={showSecret} />
Show secret
</label>
<slot showSecret={showSecret}></slot>
App.svelte
<script>
import Secret from "./Secret.svelte";
</script>
<Secret let:showSecret={isSecretShown}>
{#if isSecretShown}
<p>Hello world!</p>
{:else}
<p>***********</p>
{/if}
</Secret>
In the example above we are referencing showSecret as isSecretShown (let:showSecret={isSecretShown}) and now we can use it as a variable. Personaly, I've found a bit stange the syntax, but I think you should understand it better this way: (expose)let:(property)showSecret={(as)isSecretShown}.
Posted on March 21, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 26, 2024
November 26, 2024