Skip to content
Advertisement

Use named slots inside grand-child component

I’ve created a global components extending Bootstrap Vue Table component to made a custom template for each table named VTable.

The Bootstrap Vue Table component have possibility to use named slots to customize the data rendering.

<template>
  <div>
    <b-table
      :items="items"
      :fields="fields"
      ...
    >
    </b-table>
  </div>
</template>

<script>
  import Table from 'bootstrap-vue/es/components/table/table';

  export default {
    name: 'Vtable',
    extends: Table,
    ...
  };
</script>

I use the global table component inside another one using the new custom HTML tag.

<v-table
  v-if="items"
  :items="items"
  :fields="fields"
  ...
>
  <template
    slot="timestamp"
    slot-scope="data"
  >
    ...
  </template>
  <template
    slot="row-details"
    slot-scope="row"
  >
    ...
  </template>
</v-table>

The problem is that the named slots used in the VTable component are not displayed inside the child component.

I also tried to create a custom named slot inside the global component

<template>
  <div>
    <b-table
      ...
    >
      <slot name="customRendering"/>
    </b-table>
  </div>
</template>

And use it like

<v-table
  ...
>
  <template slot="customRendering">
    <template
      slot="timestamp"
      slot-scope="data"
    >
      ...
    </template>
    <template
      slot="row-details"
      slot-scope="row"
    >
       ...
    </template>
  </template>
</v-table>

Without success

This is possible to simply use named slots defined inside grand-child component or does it totally not possible ? I also think to loop through customRendering slot value to recreated dynamically the Bootstrap Vue table slots.

Advertisement

Answer

In your vtable component, you can define the slots you want to pass on.

so if you have a component my-component with a child -> vtable which extends -> btable

you could define the slots in your vtable component, that you want to pass along using

<template
  slot="row-details"
  slot-scope="row"
>
    <slot name="row-details"/>
</template>

here’s a quick example of this https://jsfiddle.net/eywraw8t/308324/

You may need to set this up for each slot. If you want to pass all of them along dynamically(without knowing their names), a render function would work better, since you can loop over all slots that were sent by parent, and pass them to the child.

docs: https://v2.vuejs.org/v2/guide/render-function.html#Slots

example of a component with render function that will pass down scoped slots

const Bar = Vue.component('vtable', {
  render(h) {
    const children = Object.keys(this.$slots).map(slot => h('template', { slot }, this.$slots[slot]))
    return h('wrapper', [
      h('foo', {
        attrs: this.$attrs,
        on: this.$listeners,
        scopedSlots: this.$scopedSlots,
      }, children)
    ])
  }
});
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement