Javascript is required
·
1 min read

Vue Tip: Use Scoped Slots in a Child Component to Provide Data for Parent Component

Vue Tip: Use Scoped Slots in a Child Component to Provide Data for Parent Component Image

Slots are mighty, but they are not almighty. For example, slot content does not have access to the state in the child component.

There are cases where you want to provide data for presentation in the parent component. For that, you can use Scoped Slots.

Using scoped slots, a child component can pass data to a slot when rendering it:

Child.vue
1<script setup lang="ts">
2import { ref } from 'vue'
3
4const firstName = ref('Michael')
5const lastName = ref('Hoffmann')
6</script>
7
8<template>
9  <div>
10    <slot :first-name="firstName" :last-name="lastName" />
11  </div>
12</template>

Let's first take a look at receiving props using a single default slot first. For this, we can use the v-slot directive on the child component tag:

Parent.vue
1<template>
2  <Child v-slot="slotProps">Name: {{ slotProps.firstName }} {{ slotProps.lastName }}</Child>
3</template>

The following graphic illustrates the process of passing props from the child to the parent component:

Scoped Slots

You can think of a scoped slot as a function passed into the child component. The child component then calls it, passing props as arguments:

Info

The above code almost represents how Vue compiler compiles scoped slots and how you would use them in manual render functions.

As v-slot="slotProps" matches the slot function signature, you can destructure the object in v-slot:

Parent.vue
1<template>
2  <Child v-slot="{ firstName, lastName }">Name: {{ firstName }} {{ lastName }}</Child>
3</template>

Of course, you can also use scoped slots with named slots:

Parent.vue
1<template>
2  <Child>
3    <!-- Explicit default slot -->
4    <template #default="{ firstName, lastName }">
5      <p>Name: {{ firstName }} {{ lastName }}</p>
6    </template>
7
8    <!-- Named slot -->
9    <template #footer="{ message }">
10      <p>{{ message }}</p>
11    </template>
12  </Child>
13</template>

Info

The code for this demo is interactively available at StackBlitz:

If you liked this Vue tip, follow me on X to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.