Part 3 / Component composition / Checking for slot content
The images in this exercise don't currently work. You can switch to the old tutorial instead: https://svelte.dev/tutorial/optional-slots
In some cases, you may want to control parts of your component based on whether the parent passes in content for a certain slot. Perhaps you have a wrapper around that slot, and you don't want to render it if the slot is empty. Or perhaps you'd like to apply a class only if the slot is present. You can do this by checking the properties of the special $$slots
variable.
$$slots
is an object whose keys are the names of the slots passed in by the parent component. If the parent leaves a slot empty, then $$slots
will not have an entry for that slot.
Notice that both instances of <Project>
in this example render a container for comments and a notification dot, even though only one has comments. We want to use $$slots
to make sure we only render these elements when the parent <App>
passes in content for the comments
slot.
In Project.svelte
, update the class:has-discussion
directive on the <article>
:
<article class:has-discussion={$$slots.comments}>
Next, wrap the comments
slot and its wrapping <div>
in an if
block that checks $$slots
:
{#if $$slots.comments}
<div class="discussion">
<h3>Comments</h3>
<slot name="comments"></slot>
</div>
{/if}
Now the comments container and the notification dot won't render when <App>
leaves the comments
slot empty.
<script>
import Project from './Project.svelte';
import Comment from './Comment.svelte';
</script>
<h1>Projects</h1>
<ul>
<li>
<Project
title="Add Typescript support"
tasksCompleted={25}
totalTasks={57}
>
<div slot="comments">
<Comment
name="Ecma Script"
postedAt={new Date(
'2020-08-17T14:12:23'
)}
>
<p>
Those interface tests are now passing.
</p>
</Comment>
</div>
</Project>
</li>
<li>
<Project
title="Update documentation"
tasksCompleted={18}
totalTasks={21}
/>
</li>
</ul>
<style>
h1 {
font-weight: 300;
margin: 0 1rem;
}
ul {
list-style: none;
padding: 0;
margin: 0.5rem;
display: flex;
}
@media (max-width: 600px) {
ul {
flex-direction: column;
}
}
li {
padding: 0.5rem;
flex: 1 1 50%;
min-width: 200px;
}
</style>