Conditionally Showing Elements Based on a Vue.js Slot being Populated

— 3 minute read


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!

Filed under