I recently faced a problem in a Vue.js application that I'm working on where a component had a toolbar that had some standard buttons and a slot so extra options could be added.
I wanted to show a small divider between these standard buttons and any extra ones added by the slot, so I added a span
in-between them and the slot.
<div>
<button>...</button>
<button>...</button>
<span class="divider"></span>
<slot name="actions" />
</div>
This is great until I used the toolbar without any extra actions (i.e. I didn't populate the slot), because then I have a divider element without anything to divide!
I wanted to make this divider conditional based on whether the slot was actually populated, in other words, hide it when the slot was empty, show it when the slot was populated.
I could also imagine this being handy to add extra CSS classes when a slot was populated. Perhaps to add extra padding or margins.
The $slots
Property
Within each Vue.js component there is a $slots
property which contains details of each slot that is populated (i.e. has been used and given markup by the consuming component). The important part is that a slot won't be present in this object if it hasn't been filled up.
This means that we can use the presence of our slot's name in this object as a boolean value to conditionally do things in our UI - like show/hide an element or include a CSS class!
The
$slots
property is an object with a key, mirroring the slot name, for each populated slot
Conditionally Showing the Divider
Now that we know this we can add a v-if
directive to our divider element so it is only created if the actions
slot is present in the $slots
property and therefore populated - meaning we have some buttons to separate! In our example the $slots.actions
statement will evaluate to falsey if it is missing, or truthy if present.
<div>
<button>...</button>
<button>...</button>
<span v-if="$slots.actions" class="divider"></span>
<slot name="actions" />
</div>
This is a handy little trick and can help us make our components extremely flexible and reusable in a larger number of scenarios.
Happy Vue.js-ing!