2
votes

I have a component called "List" which contains a vue boostrap table:

<template>
  <div>
    <b-table :items="items">
      <!--<template slot="createdAt" slot-scope="row"> usually vue boostrap table row templates live here-->
        <!--{{row.item.createdAt|dateFormatter}}-->
      <!--</template>-->
      <slot name="tableTemplates"></slot> <!-- but i want to pass the templates from my parent template -->
    </b-table>
  </div>
</template>

I'm passing the table items from my parent Component "Orders". I also want to pass row templates to the vue boostrap b-table component.

Unfortunately i can't get it to work using slots (That would be a template inside a template)

<template>
  <div>
    <list :items="items">
      <template slot="tableTemplates">
        <!--templates inside templates do not work-->
        <template slot="id" slot-scope="row">
          <span v-b-tooltip.hover :title="row.item.id">{{row.item.id|uuidFormatter}}</span>
        </template>
        <template slot="createdAt" slot-scope="row">
          {{row.item.createdAt|dateFormatter}}
        </template>
        <template slot="customer" slot-scope="row">
          {{row.item.customer}}
        </template>
      </template>
    </list>
  </div>
</template>
2
Have you considered creating actual components instead of using just templates?Sam Holmes
You may also be able to use inline templates.Sam Holmes

2 Answers

8
votes

You can just change IVO's answer and make your List component generic.
Here is one possible way to do that:

List component template:

<template>
  <b-table striped hover :items="items">
    <template :slot="slot.field" slot-scope="row" v-for="slot in slots">
      <slot :name="slot.name" :tbl="row"></slot>
    </template>
  </b-table>
</template>

List component props:

  props: {
    items: {
      type: Array
    },
    slots: {
      type: Array
    }
  },

Then, in any parent components (using List), you can define a templates data property, with an array of template instructions to be passed to the List component. In the example, I used an array of objects to pass the dynamic slot name and table data field.

Parent component templates data property:

  data() {
    return {
      ...
      templates: [
        {
          name: "templateName",
          field: "dataFieldName"
        },
        ...
      ]
    };
  },

Parent component template, List usage:

  <list :items="items" :slots="templates">
    <template slot="customSlotName" slot-scope="data">
        // Custom template here...
    </template>
  </list>

This will keep all your custom template logic living in the parent component, ex. Order.vue, and not in List.vue.

Here is the updated codesandbox: https://codesandbox.io/s/244p9rx10n

3
votes

Have you tried like that ? You get the scope from the table's slot and then provide this scope inside your nested slot:

<template>
  <div>
    <b-table :items="items">
      <template slot-scope="row">
        <slot name="tableTemplates" :tbl-props="row"></slot>
      </template>
    </b-table>
  </div>
</template>