Conditional Rendering of Slots

Learn how to render slots based on a conditio, using Vue 3 Composition API.


If your component accepts slots, sometimes you'll want to check if they have been provided (or not). Why? For various reasons. You might want to add specific styles using a div as a wrapper and ensure that you don't render it if there is no content — slot — to display, avoiding an empty HTML element.

Hence the conditional rendering.

Check for the existence of content for a slot

Now, how do you achieve this? With the Options API, it's straightforward because all the slots of a component are available in the object $slots. If your component has at least one slot, it will be available under $slots.default. If it has more than one slot, invoking $slots will give you an array of VNodes using their names as keys.

With this understanding, we can check if there is content for a slot and decide what to do.

<!-- MyComponent.vue instantiation-->
<MyComponent>
        <p>Slot content</p>
</MyComponent>
JS
<!-- MyComponent.vue -->
<template>
  <div>
    <h1>Slots FTW 🔥</h1>
        <div v-if="$slots.default" class="">
            <slot />    
        </div>
    <slot name="one" />
    <slot name="two" />
  </div>
</template>

Practical Case with the Composition API

I recently encountered a scenario where I wanted to use a component recursively. The difference between implementations is that in some cases, content will be passed to its slot, and in others, it won't.

For simplicity, I have created a small demo where we have a component called TableRow.vue that accepts a slot. Inside the component, we can access the list of slots with the helper useSlots, and, with a computed property, decide whether to render its content or not.

JS
import { useSlots, computed } from 'vue';
const slots = useSlots()
const hasExtraContent = computed(() => !!slots.extra);

If this is the first time you've seen the !! operator (actually, it's not an operator, it's the ! operator twice), don't worry. The first ! converts the value into its opposite boolean version, while the second ! inverts the boolean value. It's a modern way to convert an object to its Boolean equivalent. Boolean() performs the same action.

Now we can use hasExtraContent to check if the slot extra has content.

<template>
  <div class="file">
    ...
    <div v-if="hasExtraContent">
      <slot name="extra" />
    </div>
    ...
  </div>
</template>

Demo

Juan Andrés Núñez
Juan Andrés Núñez
Frontend Engineer. Vue.js Specialist. Professional Teacher. Stoic.