Vue - how to pass down slots inside wrapper component?
Solution 1
Vue 3
Same as the Vue 2.6 example below except:
-
$listeners
has been merged into$attrs
sov-on="$listeners"
is no longer necessary. See the migration guide. -
$scopedSlots
is now just$slots
. See migration guide.
Vue 2.6 (v-slot syntax)
All ordinary slots will be added to scoped slots, so you only need to do this:
<wrapper>
<b-table v-bind="$attrs" v-on="$listeners">
<template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>
</b-table>
</wrapper>
Vue 2.5
See Paul's answer.
Original answer
You need to specify the slots like this:
<wrapper>
<b-table v-bind="$attrs" v-on="$listeners">
<!-- Pass on the default slot -->
<slot/>
<!-- Pass on any named slots -->
<slot name="foo" slot="foo"/>
<slot name="bar" slot="bar"/>
<!-- Pass on any scoped slots -->
<template slot="baz" slot-scope="scope"><slot name="baz" v-bind="scope"/></template>
</b-table>
</wrapper>
Render function
render(h) {
const children = Object.keys(this.$slots).map(slot => h('template', { slot }, this.$slots[slot]))
return h('wrapper', [
h('b-table', {
attrs: this.$attrs,
on: this.$listeners,
scopedSlots: this.$scopedSlots,
}, children)
])
}
You probably also want to set inheritAttrs
to false on the component.
Solution 2
I have been automating the passing of any (and all) slots using v-for
, as shown below. The nice thing with this method is that you don't need to know which slots have to be passed on, including the default slot. Any slots passed to the wrapper will be passed on.
<wrapper>
<b-table v-bind="$attrs" v-on="$listeners">
<!-- Pass on all named slots -->
<slot v-for="slot in Object.keys($slots)" :name="slot" :slot="slot"/>
<!-- Pass on all scoped slots -->
<template v-for="slot in Object.keys($scopedSlots)" :slot="slot" slot-scope="scope"><slot :name="slot" v-bind="scope"/></template>
</b-table>
</wrapper>
Solution 3
Here is updated syntax for vue >2.6 with scoped slots and regular slots, thanks Nikita-Polyakov, link to discussion
<!-- pass through scoped slots -->
<template v-for="(_, scopedSlotName) in $scopedSlots" v-slot:[scopedSlotName]="slotData">
<slot :name="scopedSlotName" v-bind="slotData" />
</template>
<!-- pass through normal slots -->
<template v-for="(_, slotName) in $slots" v-slot:[slotName]>
<slot :name="slotName" />
</template>
<!-- after iterating over slots and scopedSlots, you can customize them like this -->
<template v-slot:overrideExample>
<slot name="overrideExample" />
<span>This text content goes to overrideExample slot</span>
</template>
Related videos on Youtube
user3599803
Updated on July 08, 2022Comments
-
user3599803 almost 2 years
So I've created a simple wrapper component with template like:
<wrapper> <b-table v-bind="$attrs" v-on="$listeners"></b-table> </wrapper>
using
$attrs
and$listeners
to pass down props and events.
Works fine, but how can the wrapper proxy the<b-table>
named slots to the child?-
Jacob Goh almost 6 yearsFYI, this is going to be solved in this new PR. But if you want to have a solution right now, this github comment would help. tested: jsfiddle.net/jacobgoh101/bptLavov/185
-
-
pouria almost 3 yearsThe answer for "Vue 2.6" doesn't work for me when using a named slot (on vue 2.6.11). If I remove the parts
="scope"
andv-bind="scope"
, it works for named slots but I can't use it for scoped slots any more :( -
Excalibaard over 2 yearsI'm having the same issue with 2.6. It seems that the issue is with trying to access the scope o non-scoped slots. Sergey's answer below has worked for me.
-
JeppePepp almost 2 yearsThis line is the magic if you wanna use the scoped slots from parent for vuetify data-tables (you wanna specify the UI for a specific column from parent component wrapping the data-table).
<template v-for="slot in Object.keys($scopedSlots)" :slot="slot" slot-scope="scope"><slot :name="slot" v-bind="scope"/></template>