How to use scoped slots in Vue

Scoped slots in Vue enable child components to pass data back to parent slot content, creating powerful template patterns where child components provide data for parent-defined rendering logic. As the creator of CoreUI, a widely used open-source UI library, I’ve implemented scoped slots in countless Vue components for data tables, lists, and flexible UI patterns where parent components need access to child data. From my expertise, the most effective approach is using slot props to pass data from child to parent with template v-slot directive for clean consumption. This method provides powerful component composition with data flow from child to parent and highly customizable rendering patterns.

Use slot props to pass data from child components to parent slot content with template v-slot directive.

<!-- Child Component: UserList.vue -->
<template>
  <div class="user-list">
    <h3>Users</h3>
    <div
      v-for="user in users"
      :key="user.id"
      class="user-item"
    >
      <!-- Scoped slot passing user data to parent -->
      <slot
        name="user"
        :user="user"
        :isActive="user.status === 'active'"
        :actions="{ edit: editUser, delete: deleteUser }"
      >
        <!-- Fallback content -->
        <div>{{ user.name }} - {{ user.email }}</div>
      </slot>
    </div>

    <!-- Default slot with summary data -->
    <slot
      name="summary"
      :totalUsers="users.length"
      :activeUsers="activeUsersCount"
    >
      <p>Total: {{ users.length }} users</p>
    </slot>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const users = ref([
  { id: 1, name: 'John Doe', email: '[email protected]', status: 'active' },
  { id: 2, name: 'Jane Smith', email: '[email protected]', status: 'inactive' }
])

const activeUsersCount = computed(() =>
  users.value.filter(user => user.status === 'active').length
)

const editUser = (user) => {
  console.log('Editing user:', user.name)
}

const deleteUser = (user) => {
  users.value = users.value.filter(u => u.id !== user.id)
}
</script>

<!-- Parent Component -->
<template>
  <div>
    <UserList>
      <!-- Using scoped slot with custom rendering -->
      <template #user="{ user, isActive, actions }">
        <div class="custom-user-card" :class="{ active: isActive }">
          <img :src="`/avatars/${user.id}.jpg`" :alt="user.name">
          <div class="user-info">
            <h4>{{ user.name }}</h4>
            <p>{{ user.email }}</p>
            <span v-if="isActive" class="status-badge">Active</span>
          </div>
          <div class="user-actions">
            <button @click="actions.edit(user)">Edit</button>
            <button @click="actions.delete(user)">Delete</button>
          </div>
        </div>
      </template>

      <!-- Using scoped slot for summary -->
      <template #summary="{ totalUsers, activeUsers }">
        <div class="summary-card">
          <h4>User Statistics</h4>
          <p>Total Users: {{ totalUsers }}</p>
          <p>Active Users: {{ activeUsers }}</p>
          <p>Inactive Users: {{ totalUsers - activeUsers }}</p>
        </div>
      </template>
    </UserList>
  </div>
</template>

Scoped slots pass data from child to parent using slot props in the slot definition. Parent components access this data using template v-slot with destructuring syntax. This enables child components to provide data while parent components control the rendering logic, creating powerful and flexible component patterns.

Best Practice Note:

This is the same scoped slot pattern we use in CoreUI Vue components for data tables, card lists, and customizable UI elements where flexible rendering is essential.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to compare dates with JavaScript
How to compare dates with JavaScript

How to replace all occurrences of a string in JavaScript?
How to replace all occurrences of a string in JavaScript?

How to force a React component to re-render
How to force a React component to re-render

How to check if a key exists in JavaScript object?
How to check if a key exists in JavaScript object?

Answers by CoreUI Core Team