Nwose Lotanna Web Developer and Writer

How to pass HTML content through components with Vue slots

5 min read 1445

How to pass HTML content through components with Vue slots

This post will introduce you to how data can be passed from the parent component to child components in Vue.js using Vue slots.

Before you start…

This post is suited for developers of all stages — including beginners — though there are some prerequisites before going through this tutorial.

You will need the following on your machine:

  • Node.js version 10.x and above installed. You can verify your version by running this command in your terminal/command prompt: node -v
  • A code editor; I highly recommend Visual Studio Code
  • Vue’s latest version, installed globally on your machine
  • Vue CLI 3.0 installed on your machine. To do this, uninstall the old CLI version first: npm uninstall -g vue-cli
  • Then, install the new one: npm install -g @vue/cli
  • Download a Vue starter project here
  • Unzip the downloaded project
  • Navigate into the unzipped file and run the command to keep all the dependencies up to date: npm install

LogRocket Free Trial Banner

What are Vue slots?

Vue slots are Vue template elements created by the Vue team to provide a platform for template content distribution. It is an implementation of the a content distribution API that was inspired by the Web Components spec draft. Using Vue slots, you can pass or distribute HTML code across various components in your project.

Why are Vue slots important?

Content distribution is important for many reasons, some of which have to do with structure. With Vue slots, you can structure an HTML interface (like with TypeScript), which you can then use as a guide to build out your components by template injection. It is a very scalable and efficient solution for passing down template code from one component to another.

Positioning of content is another great use case for Vue slots. You can just create a template and then use another component or the parent component to arrange that template as you would like it to appear in the user interface.

Slots vs. props

If you know about Vue slots, you might wonder if props and slots do the same thing. Well, the central idea of these tools or platforms is to encourage reusability and efficiency of resources. With that in mind, slots and props are similar.

Props deal with passing data objects from component to component, but slots deal with passing template (HTML) content instead from component to component. However, scoped slots act exactly like props; this will be clearly illustrated in this tutorial.

Vue slot syntax

For slots, your child component acts as the interface or structure of how you want your content arranged. It can look like this:

<template>
  <div>
    <slot></slot>
  </div>
</template>

The parent component (where the HTML content to be injected into the child component resides) can look like this:

<Test>
   <h2>Hello World!</h2>
 </Test>

This combination will return a user interface that looks like this:

<template>
  <div>
    <h2>Hello World!</h2>
  </div>
</template>

Notice how the slot on it own serves as a guide for where and how content will be injected — that is the central idea.

Demo

If you have followed this post from the start, you will have the Vue starter project open in VS Code. To illustrate the simple example in the syntax section, our parent component will be the app.vue file. Open your app.vue file and copy in this code block:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test>
      <h2>Hello World!</h2>
    </Test>
  </div>
</template>
<script>
import Test from './components/Test.vue'
export default {
  name: 'app',
  components: {
    Test
  }
}
</script>

The child component is going to be the test component, so copy the code block below in the test.vue file:

<template>
  <div>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

Run the application in the dev environment with this command:

npm run serve

[IMAGE]

Named slots

Vue allows for more than one slot for a component, which means that you can have any number of slots you want. To test this out, copy this new code block into your test.vue file:

<template>
  <div>
    <slot></slot>
    <slot></slot>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

If you run the application, you can see that hello world is printed three times. So if you want to add more content — say, a header, a paragraph with text, and then an unordered list — Vue lets us name the scopes so that it can identify the particular scope to display. Naming the slots in the test.vue file will look like this:

<template>
  <div>
    <slot name="header"></slot>
    <slot name="paragraph"></slot>
    <slot name="links"></slot>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

Now, you also have to label the HTML elements according to the slot name in which you want to display them. Copy this into the template section of your app.vue file:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test>
      <h2 slot="header">Hello world!</h2>
      <p slot="paragraph">Hello, I am a paragraph text</p>
      <ul slot="links">
        <li>Hello, I am a list item</li>
        <li>Hello, I am a list item</li>
      </ul>
    </Test>
  </div>
</template>

[IMAGE]

V-slots syntax

When Vue version 2.6 was released, it shipped with a better syntax to reference slot names from the child components called v-slot, which is meant to replace the initial slot syntax. So, instead of a parent component template with slots like this:

<Test>
   <h1 slot="header">Hello world!</h1>
</Test>

From version 3.0 (which should be released before the end of the year), it will now look like this:

<Test v-slot:header>
   <h1>Hello world!</h1>
</Test>

Notice that aside from the minor change in the string from slot to v-slot, there is also a major change: the v-slot can only be defined on templates instead of on any HTML element. This is a big change as it questions the usability of named slots, but as of this writing, slots are still very much part of the documentation.

Scoped slots

Imagine a scenario in which the Vue slot can also access the data object in the child component from the parent component — a kind of slot with props ability. To illustrate this, go ahead and create a data object in the child component by copying the code block below into the test.vue file:

<template>
  <div>
    <slot v-bind:team="team"></slot>
    <slot name="paragraph"></slot>
    <slot name="links"></slot>
  </div>
</template>
<script>
export default {
  name: 'Test',
  data(){
    return{
      team:"FC Barcelona"
    }
  }
}
</script>

Just like normal props, the v-bind directive was used to bind the team in the data with the prop reference in the parent component. Open your app.vue file and copy the code block below into the template section:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <Test v-slot="{team}">
      <h2>Hello world! my team is {{team}}</h2>
    </Test>
  </div>
</template>

If you run your application, you will see that the data object was successfully passed to the parent component. You can find the complete code for this tutorial here.

Conclusion

This post has introduced you to slots in Vue.js and how they are important to content injection. You saw how to set it up, and even how to have more than one slot for a component. You also saw how slots can also act as props by scoping. Go ahead and enjoy implementing slots in your workflow.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Nwose Lotanna Web Developer and Writer

Leave a Reply