2
votes

I am trying to make a reusable vuetify datatable. I want the ability to pass dynamic slots or item slots if I want to and both should work. This is the code

<v-data-table
    :headers="headers"
    :items="items"
    :dense="dense"
    :hide-default-header="hideDefaultHeader"
    :loading="loading"
    :options.sync="settings"
    :items-per-page="itemsPerPage"
    :server-items-length="itemLength"
    @click:row="handleClick"
    :height="height"
>
    <-- 1st part-->
    <template v-for="field in slots" v-slot:[field.field]="{ item }">
        <slot :name="field.field" :item="item"></slot>
    </template>
    <-- 2nd part -->
    <template v-slot:item="{item}">
        <slot name="item" v-bind="item"></slot>
    </template>
</v-data-table>

this is then makes a component called DataTable which I then use like this

<DataTable
    v-if="tabs == n"
    :items="items"
    :loading="loading"
    :headers="headers"
    :options="serverOptions"
    :slots="slots"
    :total="toatl"
    @updateOptions="updateOptions($event, n)"
>

I also have a slot array like this

slots: [{ field: "item.CREATOR" }, { field: "item.BODY" }]

I want the ability to either use the item slot using the 2nd part or use a specific column slot defined in the slot array 1st part. Right now the dynamic slots unless i comment out the 2nd part. This is how i currently slot each part

1st part:

<template v-slot:item.CREATOR="{ item }">
    <strong>{{item.FIRSTNAME}} {{item.LASTNAME}}</strong>
</template>

2nd part:

<template v-slot:item="item">
    <tr>
        <td>{{item.MESSAGESTATUS}}</td>
        <td>sdsd</td>
        <td>sfsf</td>
    </tr>
</template>
1

1 Answers

4
votes

What you are trying to do may be easly solved using computed properties for the dynamic slots you wish:

 computed: {
   creatorSlots: function () {
    //Filters the slots of type CREATOR
    return this.slots.filter(slot => slot.field==='CREATOR');
   }
 }

so now you can use your First Part for every 'CREATOR' slot on your slots array:

<template v-for="(slot,i) in creatorSlots" v-slot:[`item.${slot.field}`]="{ item }">
    <strong :key="i">{{item.FIRSTNAME}} {{item.LASTNAME}}</strong>
</template>

If you have other slots that need to be processed in another way you only need to use another computed property for your other slots and repeat the process...

 computed: {
   bodySlots: function () {
    //Filters the slots of type BODY
    return this.slots.filter(slot => slot.field==='BODY');
   }
 }
<template v-for="(slot,i) in bodySlots" v-slot:[`item.${slot.field}`]="{ item }">
    <tr>
        <td>{{item.MESSAGESTATUS}}</td>
        <td>sdsd</td>
        <td>sfsf</td>
    </tr>
</template>

Hope it helps, I came to here with a similar problem that I solved this way.