Use Slot Vue Js

bySai gowtham

Use Slots to Make Your Components Easier to Understand and More Powerful I recently wrote an article about some important things you need to know regarding slots in Vue.js. It highlights how slots can make your components more reusable and easier to maintain and why you should use them. Get the Most Out of This Course Create Your First Vue App Store and Manage Data Manage Common Scenarios With Directives Part 1 Summary Quiz: Build a Vue.js Application Create a New Project With Vue CLI Manage Complexity With Single-File Components Manage Navigation With Vue Router Determine When Your Code Should Run Part 2 Summary Quiz: Scale Your Application With Vue CLI Manage Styles in Your. Vue provides a way of extracting and reusing the state and logic of a component, but the template is deemed single-use only. In this article, I'll show you a hack for extending templates using HTML pre-processing. Say hi to the first Vue tidbit πŸ‘‹ It’s about time I start covering Vue in my code tidbits, right πŸ˜‰β€¬ Use the new named slot shorthand with β€œ#”. This is available now in Vue 2.6.0+ πŸ‘.

In this tutorial, we will learn about how to use the slots in vue.js with the help of examples.

What are Slots?

Slots helps us to pass the data between opening and closing component tags.

In vue.js props are used to pass the data to its child components, but it is hard to pass when we have a complex code. In such cases slots can be used.

Let’s create a new component called Post by adding the <slot> element.

Now, if we pass any content between the Post component opening and closing tags that are rendered in the place of <slot></slot> element.

Output:

Named Slots

Sometimes, we need to pass the data to a specific places in such cases named slots can be used.

The named slots can be created by adding a name attribute to the <slot> element.

To pass the content to the named slots we need to use v-slot directive on template providing slot name as v-slot argument.

Fallback data

In some cases, we can use fallback data (aka default) when data is not passed to a slot.

For example:

In the above component, we have added a Submit text inside a slot element.

Now, If we use a my-button component without passing any data we can seethe fallback data Submit text is rendered inside the button.

Output of rendered html:

But, if we pass data to the my-button component fallback data is replaced.

Output of rendered html:

Do you find yourself wanting to extend a component's template? Vue provides several means of extracting and reusing the component logic and state, but templates are deemed single-use only.

Use Slot Vue Js Download

In this article, I'll present a solution using the HTML template pre-processor Pug. It's a bit of a hack, but it does work!

If you're looking to extend a component's logic and state, you probably want to read my other article Extending Vue.js Components which covers composition functions, mixins, higher-order components, etc. Here we're talking about the template.

Case study: a survey app

Let's say you're trying to make a component-based survey app with Vue which looks like this:

Use slot vue js download

Notice that each survey question has a different input type:

  1. Text input
  2. Select input
  3. Radio input

An obvious architecture would be to make each question into a separate component, which is what we're going to do. Well name these components:

  1. SurveyInputText
  2. SurveyInputSelect
  3. SurveyInputRadio

Base component

Let's first create a 'base' component called SurveyInput.vue. Notice the following about it:

  • The question prop is going to be common across each component. This captures the question text e.g. 'What is your name'.
  • We don't have any shared logic, but you could add it e.g. validation and error logic
  • I'm leaving a gap where the input element will need to go. This is where we'll extend the template as you'll shortly see.

SurveyInput.vue

State and logic reuse

Ignoring the template for a moment, what will be our strategy for extraction and reuse of the state/logic? What we choose here will not affect our ability to extend the component template, so feel free to use mixins, higher-order components, or even the new composition API. I'm going to keep it simple and use the extends component option.

Again, there's still a hanging question about how we get the base template into this subcomponent, as the Vue.extends API doesn't apply to templates!

SurveyInputText.vue

Never miss a new post!

Get our latest post in your inbox every Tuesday by subscribing to the Vue.js Developers Newsletter .

This subscription also includes Vue.js Developers promotional emails. You can opt-out at any time. View our privacy policy .

This form is protected by reCAPTCHA. The Google privacy policy and terms of service apply.

Conventional options for extending the template (and why they aren't ideal)

A reasonable Vue user would first consider the following design patterns for the template:

  • Props-driven template logic
  • Slots

But as I'll show, both have downsides for the use case we're considering, so there is a legitimate case for wanting to use the template-extension hack I'm going present.

Props-driven template logic

Rather than making separate components for each input type, you could create a single mega-component and then specify the template using conditional logic fed by a prop called question-type i.e.

SurveyInput.vue

Now you can declare your questions in the parent, Survey.vue, like this:

Survey.vue

The downside of this approach is that it doesn't scale well. Once you get, say, 3-4 different question types the template will become big and messy.

Slots

Another conventional approach that could work is to put a slot where the input belongs.

Use Slot Vue Js

SurveyInput.vue

Using this approach the parent can provide the correct markup for each input like this:

Survey.vue

The downside to slots, though, is that you now have to organize the data model differently. Now, the parent owns the state of each input and would have to communicate it with each child component using props/events, adding complex logic and verbosity.

Survey.vue

Hopefully, I've convinced you that template logic and slots aren't ideal, so now let's look at how we can extend a component's template like we can with its state/logic.

To do this, we're going to need an HTML template pre-processor.

Pug HTML pre-processor

By using vue-loader and the lang property of the template in a single-file component, we can use HTML template pre-processing tools like Slim, Handlebars, etc.

My hack for extending Vue templates is to use the include and extends options provided by Pug (previously Jade).

First, add Pug to your project. Vue Loader should pick this up without any further config needed.

Now, let's convert our base component's template to Pug syntax:

Notice that we use block input to declare an 'outlet' where the subcomponent content will be distributed.

Important: the outlet is kind of like a slot but the important difference is that template processing occurs at compile-time, not at run-time as it would with slots.

Creating a base template

So here's where it gets slightly messy. If we want our child components to extend the template we first need to put it into its own file SurveyInput.pug:

SurveyInput.pug

Now we can include this file in our base component so it can still be used as a normal single-file component:

SurveyInput.vue

It's a shame to have to do that since it kind of defeats the purpose of 'single file' components. Probably someone could make a custom webpack loader to avoid having to do this.

Use Slot Vue Json

Extending to a subcomponent

To extend the subcomponent's template from the base, you'll need to covert its template to Pug as well.

The subcomponents use the extends feature of Pug which includes the base component and outputs any custom content in the input block (again, similar to slots, but it happens at compile-time).

SurveyInputText.vue

Here's what the subcomponent's template would effectively look like after extending the base and being translated to a regular HTML Vue template:

Bring it all together

Use Slot Vue Js

Using this strategy we can go ahead and create the other two subcomponents SurveyInputSelect and SurveyInputRadio. If we then use them in a project our main template might look like this:

Survey.vue

And here's how the rendered markup would look:

Happy hacking!