We use cookies to enhance your experience on the site
CodeWorlds

Scoped Slots

In NOVA LAB the inventory system provides data about each cargo module, but the operator decides how to display it - as a list, table, or cards. Scoped slots are a mechanism for passing data from a child to a parent through a slot.

The Problem

Regular slots give the parent control over appearance, but what if the child has data the parent should use? For example, the child iterates over a list and wants to give the parent control over rendering each item.

Passing Data Through a Slot

The child passes data as attributes on the

<slot>
tag:

1<!-- ModuleList.vue (child) -->
2<script setup>
3import { ref } from 'vue'
4const items = ref([
5  { id: 1, name: 'Oxygen Tank', status: 'loaded' },
6  { id: 2, name: 'Water Filter', status: 'pending' },
7  { id: 3, name: 'Solar Cell', status: 'damaged' }
8])
9</script>
10
11<template>
12  <div class="module-list">
13    <div v-for="item in items" :key="item.id">
14      <slot :item="item" :index="item.id">
15        <!-- Fallback: simple rendering -->
16        <p>{{ item.name }}</p>
17      </slot>
18    </div>
19  </div>
20</template>

Receiving Data in the Parent

The parent uses

v-slot
or
#default
with an argument:

1<template>
2  <!-- Full syntax -->
3  <ModuleList v-slot="slotProps">
4    <div class="card">
5      <h3>{{ slotProps.item.name }}</h3>
6      <span>{{ slotProps.item.status }}</span>
7    </div>
8  </ModuleList>
9
10  <!-- With destructuring -->
11  <ModuleList v-slot="{ item, index }">
12    <div class="card">
13      <h3>#{{ index }}: {{ item.name }}</h3>
14      <span :class="item.status">{{ item.status }}</span>
15    </div>
16  </ModuleList>
17</template>

Named Scoped Slots

Scoped slots also work with named slots:

1<!-- DataTable.vue -->
2<template>
3  <table>
4    <thead>
5      <tr>
6        <slot name="header">
7          <th>Name</th>
8          <th>Status</th>
9        </slot>
10      </tr>
11    </thead>
12    <tbody>
13      <tr v-for="item in items" :key="item.id">
14        <slot name="row" :item="item">
15          <td>{{ item.name }}</td>
16          <td>{{ item.status }}</td>
17        </slot>
18      </tr>
19    </tbody>
20  </table>
21</template>
22
23<!-- Parent -->
24<DataTable>
25  <template #header>
26    <th>Module Name</th>
27    <th>Current Status</th>
28    <th>Actions</th>
29  </template>
30
31  <template #row="{ item }">
32    <td>{{ item.name }}</td>
33    <td>{{ item.status }}</td>
34    <td><button>Inspect</button></td>
35  </template>
36</DataTable>
Go to CodeWorlds