Categories
JavaScript Vue

Vue Components — Dynamic Slot Names and Shorthands

Spread the love

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at add dynamic slot names.

Dynamic Slot Names

Since Vue.js 2.6.0, we can pass in dynamic slot names with v-slot . For example, we can use it as follows:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user" name='first-name'></slot>  
    <slot v-bind:user="user" name='last-name'></slot>  
  </p>`  
});

new Vue({  
  el: "#app",  
  data: {  
    firstname: "first-name",  
    lastname: "last-name"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template v-slot:[firstname]="{ user }">  
          {{ user.firstName }}  
        </template>  
        <template v-slot:[lastname]="{ user }">  
          {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, firstname and lastname in data are set as the names of the slots in our root template.

Named Slots Shorthand

v-slot has a shorthand. We can shorten v-slot: to the symbol # . For example, we can rewrite our example as follows:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user" name='first-name'></slot>  
    <slot v-bind:user="user" name='last-name'></slot>  
  </p>`  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template #first-name="{ user }">  
          {{ user.firstName }}  
        </template>  
        <template #last-name="{ user }">  
          {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

For referencing the default slot, we have to write #default . For example, we write:

src/index.js :

Vue.component("user", {  
  data() {  
    return {  
      user: {  
        firstName: "Joe",  
        lastName: "Smith"  
      }  
    };  
  },  
  template: `<p>  
    <slot v-bind:user="user"></slot>      
  </p>`  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <user>  
        <template #default="{ user }">  
          {{ user.firstName }} {{ user.lastName }}  
        </template>  
      </user>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Use with v-for

We can add a slot to provided fallback content in lists and allow us to change the content in the parent. For example, we can write the following:

src/index.js :

Vue.component("people", {  
  data() {  
    return {  
      persons: [  
        { name: "Joe", isAdult: true },  
        { name: "Jane", isAdult: false }  
      ]  
    };  
  },  
  template: `  
    <ul>    
      <li v-for='person of persons'>  
        <slot v-bind:person="person"></slot>      
      </li>  
    </ul>  
  `  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <people v-bind:persons="persons">  
        <template #default="{ person }">  
          {{person.name}}  
          <span v-if="person.isAdult"> - Adult</span>  
          <span v-else> - Child</span>  
        </template>  
      </people>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we have the people component with persons data. We rendered persons with v-for in the people component and make the entries available via v-bind :

<slot v-bind:person="person"></slot>

Then in the root template, we have:

<people v-bind:persons="persons">  
  <template #default="{ person }">  
    {{person.name}}  
    <span v-if="person.isAdult"> - Adult</span>  
    <span v-else> - Child</span>  
  </template>  
</people>

to get person from people and then provide a template to display the entries as we wish without modifying the people component.

Conclusion

Since Vue 2.6.0, we can use dynamic slot names instead of hard-coded ones.

Also, the shorthand for named slots is # . For default slots, we always have to write #default .

Finally, we can use it with v-for to let us define a template that can be used with each entry. We use v-bind on the entry of the array instead of the whole array and then we can access that data in the parent component and add a templarte to display data the way we like by defining it in the parent.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *