1

I'm using Vuetify and made a component including a v-data-table. How could I change the table column templates in the parent component?

Child component example:

<template>
  <v-card>
    <v-data-table :items="items" :headers="headers">
      <!-- ???????? -->
    </v-data-table>
  </v-card>
</template>

<script>
export default {
  name: "ChildComponent",
  props: {
    items: Array,
    headers: Array,
  },
};
</script>

Parent component:

The item.id is just an example, I need a common solution for any kind of object field.

<template>
  <ChildComponent :items="items" :headers="headers">
    <template v-slot:item.id="{ item }">
      <v-chip> {{ item.id }} </v-chip>
    </template>
  </ChildComponent>
</template>

<script>
import ChildComponent from "./ChildComponent";

export default {
  components: {
    ChildComponent,
  },
  data: () => ({
    items: [/* ... */],
    headers: [/* ... */],
  }),
};
</script>

I guess I need dynamic slots but not really know how to use them in this case.

KDani
  • 358
  • 4
  • 19
  • I think you're looking to create component [slots](https://vuejs.org/v2/guide/components-slots.html), specifically of the [named variety](https://vuejs.org/v2/guide/components-slots.html#Named-Slots). – zcoop98 Oct 05 '20 at 21:27

2 Answers2

5

Need to modify the ChildComponent on the following way:

<template>
  <v-card>
    <v-data-table :items="items" :headers="headers">
      <template
        v-for="header in headers"
        v-slot:[`item.${header.value}`]="{ item }"
      >
        <slot :name="[`item.${header.value}`]" :item="item">
          {{ getVal(item, header.value) }}
        </slot>
      </template>
    </v-data-table>
  </v-card>
</template>

<script>
export default {
  name: "childComponent",
  props: {
    items: Array,
    headers: Array,
  },
  methods: {
    /*
    https://stackoverflow.com/a/40270942/6936938
    */
    getVal(item, path) {
      return path.split(".").reduce((res, prop) => res[prop], item);
    },
  },
};
</script>

The getVal method is for the nested item fields. Without it you can't use paths like item.author.name.

KDani
  • 358
  • 4
  • 19
1

Try to create a scoped slot in the child component with item.id as name and pass item as scoped value :

   <v-data-table :items="items" :headers="headers">
       <template v-slot:item.id="{ item }">
         <slot :name="item.id" :item="item"></slot>
       </template>
    </v-data-table>
Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
  • I need a common solution, the `id` field is just an example. When I iterate over the header values with `` that works, the only problem that every column template will be overriden instead of only one. – KDani Oct 05 '20 at 21:34
  • please update your question with these details in readable format – Boussadjra Brahim Oct 05 '20 at 21:39
  • Found and posted the solution, it was a bit tricky. – KDani Oct 05 '20 at 21:58