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.