1
votes

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.

1

1 Answers

1
votes

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://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)
    ])
  }
});