Recursive scoped slots

I have a use case (navigation tree) where I want to have slots replaced in a component and forward that same slots to all the children.

Here is a JSFiddle:

In this example we see that the slot is correctly overridden in the root recursive-item component, but not in the children ones.
If tried to “duplicate” the slot, but it then indicates that 2 default slots exist in the rendering tree.

Any idea how I can forward a user provided template for a slot to children elements?

PS: the example has been simplified to allow better reasoning. In the real use case, 1 recursive item can have multiple children of type recursive-item.



I think, you can solve your problem with a render function. It seems to be possible (I’m still a beginner) to pass the original scoped slots function down to the next invocation of the recursive component.

Here’s a .vue file:

    <recursive-item :level="1">
        <template scope="props">
            This is lovely level {{props.level}}.

const RecursiveItem = {
    props: {level: Number},
    render(h) {
        if (this.level < 5) {
            return h('ul', [
                h('li', [
                    this.$scopedSlots.default({level: this.level}),
                    h(RecursiveItem, {
                        props: {level: this.level + 1},
                        scopedSlots: {default: this.$scopedSlots.default}

export default {
    components: {


Thanks for the answer @sma, I will give that a try.

I was hoping to find out an easier solution than writting render functions, given my real use case is far more complex than the fiddle share :wink:

I’ll share my feedback here after the attempt.

It worked like a charm @sma

Here is the working version:

Thanks a lot.

It can be done without using render functions, if you don’t need a default template and/or it is acceptable to use a helper component to supply the default template.

Here is my TreeView implementation using the wrapper method:


To anyone passing by, note Paul’s solution on stack overflow, with automatic passing of slot, clean, doesn’t need a wrapper and works great with default:

  <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>


Here is the fiddle.


Thanks, here’s the version with the new syntax as of 2.6.0+

<!-- Pass on all scoped slots -->
<template v-for="slot in Object.keys($scopedSlots)" v-slot:[slot]="scope">
  <slot :name="slot" v-bind="scope"/>

Thank you!