Skip to content

Effortlessly forward slots to child components in Vue 3 applications.

Notifications You must be signed in to change notification settings

jessegall/vue-forward-slots

Repository files navigation

Vue Forward Slots

Effortlessly forward slots to child components in Vue 3 applications.

Features

  • Easily forward all slots or specific slots to child components
  • Simple and declarative syntax

Why Vue Forward Slots?

In Vue applications, it's common to need to forward slots from a parent component to a child component. However, the default way of doing this can be verbose and repetitive. Consider the following example:

The Default Way

<template>
    <ChildComponent>
        <template v-for="(index, name) in $slots" v-slot:[name]="data">
            <slot :name="name" v-bind="data"/>
        </template>
    </ChildComponent>
    <AnotherChildComponent>
        <template v-for="(index, name) in $slots" v-slot:[name]="data">
            <slot :name="name" v-bind="data"/>
        </template>
    </AnotherChildComponent>
</template>

Verbose and hard to read!

With Vue Forward Slots

<template>
    <ForwardSlots :slots="$slots">
        <ChildComponent/>
        <AnotherChildComponent/>
    </ForwardSlots>
</template>

Simple and clean!

Installation

npm install vue-forward-slots

Importing

You can import it in the component where you want to use it.

<script>
    import {ForwardSlots} from "vue-forward-slots";

    ...
</script>

Usage

Example Usage

A classic example is that of a table component with multiple levels of nested components. We can easily define and forward slots to nested components using the ForwardSlots component.

Root Component

We define the slots in the root component.

<template>
    <TableComponent>
        <template #name-header>
            <p class="font-bold">
                Name
            </p>
        </template>

        // We still have access to the slot data like we would normally
        <template #status-cell="{ user }">
            <StatusBadge :status="user.status"/>
        </template>
    </TableComponent>
</template>

Table Component

We forward the slots to the child components.

<template>
    <table>
        // Notice that we can wrap multiple components in the ForwardSlots component
        <ForwardSlots :slots="$slots">
            <TableHeadComponent/>
            <TableBodyComponent/>
        </ForwardSlots>
    </table>
</template>

TableHead Component

The TableHeadComponent now has access to the slots defined in the root component. If no slot is provided, it will default to the text in the slot.

<template>
    <thead>
    <tr>
        <th>
            <slot name="name-header">
                Some default text
            </slot>
        </th>
        <th>
            <slot name="status-header">
                Some default text
            </slot>
        </th>
    </tr>
    </thead>
</template>

TableBody Component

The TableBodyComponent also has access to the slots defined in the root component. Notice how we also pass the user data.

<template>
    <tbody>
    <tr v-for="user in users">
        <td>
            <slot name="name-cell" :user="user">
                {{ user.name }}
            </slot>
        </td>
        <td>
            <slot name="status-cell" :user="user">
                {{ user.status }}
            </slot>
        </td>
    </tr>
    </tbody>
</template>

We could even go a step further and forward the slots to the next level of child components.

<template>
    <thead>
    <tr>
        <th v-for="header in headers">
            <ForwardSlots :slots="$slots">
                <TableHeaderCell :header="header"/>
            </ForwardSlots>
        </th>
    </tr>
    </thead>
</template>

In theory, we could keep forwarding slots to as many levels of child components as we need.

Forwarding Only Specific Slots

<template>
    // For a single slot
    <ForwardSlots :slots="$slots" only="header">
        <MyComponent/>
    </ForwardSlots>

    // For multiple slots
    <ForwardSlots :slots="$slots" :only="['header', 'footer']">
        <MyComponent/>
    </ForwardSlots>
</template>

Excluding Specific Slots

<template>
    // For a single slot
    <ForwardSlots :slots="$slots" except="sidebar">
        <MyComponent/>
    </ForwardSlots>

    // For multiple slots
    <ForwardSlots :slots="$slots" :except="['sidebar', 'footer']">
        <MyComponent/>
    </ForwardSlots>
</template>

About

Effortlessly forward slots to child components in Vue 3 applications.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published