Suppose I have a component with data:
data: function () {
return {
slots: [
{ Id: 1, slotName: 'apple', componentName: 'Apple' },
{ Id: 2, slotName: 'banana', componentName: 'Banana' }
]
}
}
and I want to pass the list of slots as scoped slots to a child component. The following syntax won't work because you cannot use v-for on a template element:
<child-component>
<template v-for="slot in slots" :key="slot.Id" v-slot[slot.slotName]="slotProps">
<component :is="slot.componentName" :someProp="slotProps"></component>
</template>
</child-component>
and the following syntax won't work because in Vue 2.6.0+ any content not wrapped in a <template> using v-slot is assumed to be for the default slot
.
<child-component>
<component v-for="slot in slots" :key="slot.Id"
:is="slot.componentName" v-slot[slot.slotName]="slotProps" :someProp="slotProps"></component>
</child-component>
The following will work but the compiler throws a warning and it uses deprecated syntax:
<child-component>
<component v-for="slot in slots" :key="slot.Id"
:is="slot.componentName" :slot="slot.slotName" slot-scope="slotProps" :someProp="slotProps"></component>
</child-component>
Is there any way to achieve this using non-deprecated Vue template syntax and without using a render function?
How to use it. Using the slot is very easy, we should just write the <slot> component (which is a reserved word in Vue. js) inside the child component's template, where we want to receive data. A child component uses slot.
Vue dynamic components enable users to switch between two or more components without routing, and even retain the state of data when switching back to the initial component. The central idea is to let users dynamically mount and unmount components in the user interface without using routers.
There are two steps to using named slots in Vue: Naming our slots from our child component using the name attribute. Providing content to these named slots from our parent component using the v-slot directive.
slotProps is just a variable we used to access the props we passed. You can also avoid setting a variable just to hold the props you pass to the child component, by destructuring the object on the fly: <page> <template v-slot="{ dogName }"> {{ dogName }} </template> </page>
You can use v-for into a template component
You just need to specify the key
on the component
.
<child-component>
<template v-for="slot in slots" v-slot:[slot.slotName]="slotProps">
<component :key="slot.Id" :someProp="slotProps"></component>
</template>
</child-component>
I had to generate the slot name dynamically. Based on @EzequielFernandez's answer, I did it using a function :
<template v-for="locale in locales" v-slot:[getSlotName(locale)]="slotProps">
...
</template>
data() {
return {
locales: ['en', 'fr']
}
},
methods: {
getSlotName(locale) {
return `locale-${locale}`
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With