Tutorial

How To Use Scoped Component Slots in Vue.js

Vue.js

Introduction

While component slots satisfy some use cases, there are other scenarios where you want the template inside the slot to be able to access data from the child component hosting the slot content. For example, if you are trying to allow custom templates in a container while still retaining access to those containers’ data properties, you will want to use a scoped slot.

Scoped component slots are a feature introduced in Vue 2.1.0. They allow you to pass properties from your child components into a scoped slot and access them from the parent. Sort of like reverse property passing.

In this tutorial, you will explore an example Vue project with a parent component and child component that shares properties with scoped component slots.

Prerequisites

If you would like to follow along with this article, you will need:

Note:

In Vue 2.6.0, the syntax for slots was changed. This tutorial will cover the 2.6.0 syntax.

This tutorial was verified with Node v15.10.0, npm v7.6.0, and vue v2.6.11.

Using Scoped Component Slots

To create scoped component <slot>, you will first need to pass properties into a named or unnamed slot from your child component.

Here is an example of a ChildComponent that contains unnamed and named <slot> elements:

ChildComponent.vue
<template>
  <div>
    <p>This is a child component.</p>
    <div>
      <p>Default Slot</p>
      <slot v-bind:text="defaultSlotText"></slot>
    </div>
    <div>
      <p>Named Slot</p>
      <slot name="namedSlot" v-bind:text="namedSlotText"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      defaultSlotText: "Default Slot Text",
      namedSlotText: "Named Slot Text"
    }
  }
}
</script>

Then, to use those properties inside a parent component’s v-slot content, create a <template> element tied to the child component’s <slot> element.

Add an attribute to the <template> element and set it to the name that you wish to access the scope properties from. This essentially creates a local variable for anything inside that template, allowing you to access it as if it was in the parent’s scope.

For example, "firstScope", properties passed into the <slot> will be accessible as {{firstScope.exampleProperty}} while secondScope" will be accessed as {{secondScope.exampleProperty}}.

Here is an example of a ParentComponent that references the defaultSlotText and namedSlotText:

ParentComponent.vue
<template>
  <div>
    <p>This is a parent component.</p>
    <ChildComponent>
      <template v-slot="defaultSlotText">
        <p>{{defaultSlotText.text}}</p>
      </template>
      <template v-slot:namedSlot="namedSlotText">
        <p>{{namedSlotText.text}}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
}
</script>

Viewing the application in a web browser will produce the following result:

Output
<div> <p>This is a parent component.</p> <div> <p>This is a child component.</p> <div> <p>Default Slot</p> <p>Default Slot Text</p> </div> <div> <p>Named Slot</p> <p>Named Slot Text</p> </div> </div> </div>

The defaultSlotText.text and namedSlotText.text are passed from the child component to the parent component.

Conclusion

In this tutorial, you explored an example Vue project with a parent component and child component that shares properties with scoped slots.

If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.

Creative Commons License