Vue and Bootstrap Vue - dynamically use slots

2020-07-18 09:12发布

问题:

I'm trying to make in a bootstrap-vue table a slot to render any boolean value with a custom component.

So I have a simple table

<b-table :items="items" :fields="columns" >

</b-table>

Now if i want to render a single column in a particular way i have to use a slot

<template v-slot:cell(active)="data" >
    <my-component :item="data.item" />
</template>

And it works, because I know that active is a boolean.

I would like to generalize this behavior but i cannot use v-for in templates and cannot use v-slot:cell(active) if not on template... The idea was to create an array with all my boolean fields and iterate on it... but it does not work..

Something like this

<template v-slot:cell(b)="data" v-for="b in booleanFields">
    <my-component :item="data.item[b]" />
</template>

回答1:

Because Vue supports Dynamic Slot Names, you can use variables to set the slot names using the v-bind:[attributeName]="value" syntax.

This way you could do something like:

<template v-slot:['cell(' + b + ')']="data" v-for="b in booleanFields">

But using the quotes there is not possible due to the dynamic argument expression constraints. So you'll have to create a helper method to do that concatenation. So:

<template v-slot:[gomycell(b)]="data" v-for="b in booleanFields">

plus

methods: {
  gomycell(key) {
    return `cell(${key})`; // simple string interpolation
  }

Naturally, you could just name the method gomycell as cell and use it like v-slot:[cell(b)]="data" (notice the []s), but I left the name gomycell just so in this texample it is clearer what is the name of the method and what is not.


Demo:

Here's a small demo showcasing the dynamic slot names usage, it's not b-table but I think it is good enough to show it is possible:

Vue.component('my-table', {
  template: '#my-table',
})

new Vue({
  el: '#app',
  data: {
    booleanFields: [true, false]
  },
  methods: {
    gomycell(key) {
      return `cell(${key})`;
    }
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <my-table>
    <template v-slot:[gomycell(b)]="data" v-for="b in booleanFields">
      <h3>who? {{ data.is }}</h3>
    </template>
  </my-table>
</div>

<template id="my-table">
  <div>
    <div style="color:green"><slot name="cell(true)" v-bind="{is: 'true!'}"></slot></div>
    <div style="color:red"><slot name="cell(false)" v-bind="{is: 'false!'}"></slot></div>
  </div>
</template>