3

I want to make a reusable Data Table component from Vuetify. Some columns could contain v-slot to modify the data inside that column. For example: I store the user roles as integers and want them displayed as user or adminin the table. Currently I do this with thisv-slot`:

 <template v-slot:item.role="{item} ">
    {{ (item.role === 1) ? 'Administrator' : 'User' }}
 </template>

Because this will not be the use-case for every Data Table I want to pass these v-slot from a parent component which uses the Data Table. My Data Table component currently looks like this:

<template>
  <v-data-table :headers="headers" :items="items">
    <template v-slot:item.role="{item} ">
      {{ (item.role === 1) ? 'Administrator' : 'User' }}
    </template>
    <template v-slot:item.action="{ item }">
      <v-icon @click="deleteItem(item)" small>fas fa-trash</v-icon>
    </template>
  </v-data-table>
</template>

<script>
export default {
  name: "DataTable",
  props: {
    title: String,
    headers: Array,
    items: Array
  },
  methods: {
    deleteItem(item) {
      this.$emit("clicked", item);
    }
  }
};
</script>

And this is the component (UserTable.vue) where I use the DataTable:

<template>
  <DataTable :title="title" :headers="headers" :items="items" @clicked="onDelete" />
</template>

<script>
import DataTable from "../../../components/DataTable";
import axios from "axios";

export default {
  name: "UserTable",
  components: {
    DataTable
  },
  props: {
    items: Array
  },
  data: () => ({
    title: "Users",
    headers: [
      {
        text: "Name",
        value: "name"
      },
      {
        text: "Email",
        value: "email"
      },
      {
        text: "Role",
        value: "role"
      },
      { text: "Actions", value: "action", sortable: false }
    ],
  }),
  methods: {
    onDelete(item) {
      this.$emit("clicked", item);
    }
  }
};
</script> 

In an ideal situation I would like to have it something like this in the UserTable component:

<template>
  <DataTable :title="title" :headers="headers" :items="items" @clicked="onDelete">
      <template v-slot:item.role="{item} ">
      {{ (item.role === 1) ? 'Administrator' : 'User' }}
    </template>
    <template v-slot:item.action="{ item }">
      <v-icon @click="deleteItem(item)" small>fas fa-trash</v-icon>
    </template>
  </DataTable>
</template>

And then keep the DataTable clean and simple like this:

<template>
  <v-data-table :headers="headers" :items="items">
    <slot></slot>
  </v-data-table>
</template>

But that obviously doesn't seem to work as I expected because it doesn't show anything in the desired columns now. I created a CodeSandBox to let you see how I have it now:

https://codesandbox.io/s/priceless-bohr-oxu18?fontsize=14&hidenavigation=1&theme=dark

Can someone tell me why my approach doesn't work or how I might fix this?

Baspa
  • 1,099
  • 1
  • 18
  • 49
  • 1
    Does this answer your question? [vue - how to pass down slots inside wrapper component?](https://stackoverflow.com/questions/50891858/vue-how-to-pass-down-slots-inside-wrapper-component) – Flame Jan 06 '20 at 13:17

1 Answers1

4

I managed to fix this by looking at this answer: https://stackoverflow.com/a/52823029/7603806

<template v-for="slot in Object.keys($scopedSlots)" :slot="slot" slot-scope="scope"><slot :name="slot" v-bind="scope"/></template>

I added the code above in my DataTable component and pass the slots now from the UserTable component which uses the DataTable.

Baspa
  • 1,099
  • 1
  • 18
  • 49