Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

V-data-table controlling expanded items via v-slot:body

Tags:

vuetify.js

The documentation on vuetify 2.0 v-data-tables doesn't specify how to control the expanded items via the v-slot:body. I have a table i need to specify with the body v-slot and would like to use the expand feature.

Expected behavior is by clicking the button in one column in the table, the row expands below.

I'm using the v-slot:body as i will need to fully customize the column content. I'm migrating the code from vuetify 1.5 where props.expanded enabled this functionality.

Codepen: https://codepen.io/thokkane/pen/PooemJP

<template>
  <v-data-table
    :headers="headers"
    :items="deserts"
    :expanded.sync="expanded"
    :single-expand="singleExpand"
    item-key="name"
    hide-default-footer
  >
    <template v-slot:body="{ items }">
      <tbody>
        <tr v-for="item in items" :key="item.name">
          <td>
            <v-btn @click="expanded.includes(item.name) ? expanded = [] : expanded.push(item.name)">Expand</v-btn>
          </td>
        </tr>
      </tbody>
    </template>
    <template v-slot:expanded-item="{ headers, item }">
      <span>item.name</span>
    </template>
  </v-data-table>
</template>

<script>
  export default {
    data () {
      return {
        expanded: [],
        singleExpand: false,
        headers: [
          { text: 'Dessert (100g serving)', align: 'left', sortable: false, value: 'name' },
          { text: 'Calories', value: 'calories' },
          { text: 'Fat (g)', value: 'fat' },
          { text: 'Carbs (g)', value: 'carbs' },
          { text: 'Protein (g)', value: 'protein' },
          { text: 'Iron (%)', value: 'iron' },
          { text: '', value: 'data-table-expand' },
        ],
        desserts: [
          {
            name: 'Frozen Yogurt',
            calories: 159,
            fat: 6.0,
            carbs: 24,
            protein: 4.0,
            iron: '1%',
          },
          {
            name: 'Ice cream sandwich',
            calories: 237,
            fat: 9.0,
            carbs: 37,
            protein: 4.3,
            iron: '1%',
          },
          {
            name: 'Eclair',
            calories: 262,
            fat: 16.0,
            carbs: 23,
            protein: 6.0,
            iron: '7%',
          },
        ],
      }
    },
  }
</script>
like image 257
findev Avatar asked Nov 06 '19 05:11

findev


1 Answers

When you use v-slot:body together with v-slot:expanded-item, you are overriding your changes inside v-slot:expanded-item. This is because expanded-item slot is inside the body slot. If you are going to use body for customization, you unfortunately have to customize everything inside.

Imagine a structure like this:

<div slot="body">
  <div slot="item">...</div>
  <div slot="expanded-item">...</div>
  etc...
<div>

So in this case <template v-slot:body> will replace <div slot="body"> and anything inside. Therefore usage of <template v-slot:expanded-item> will not work with <template v-slot:body>. Besides v-slot:body props does not include item-specific properties and events like select(), isSelected, expand(), isExpanded etc.

I would recommend you to use v-slot:item instead. You can accomplish same thing without needing to customize everything with less code.

Something like this should work:

<template v-slot:item="{ item, expand, isExpanded }">
  <tr>
    <td>
      <v-btn @click="expand(!isExpanded)">Expand</v-btn>
    </td>
    <td class="d-block d-sm-table-cell" v-for="field in Object.keys(item)">
      {{item[field]}}
    </td>
  </tr>
</template>

<template v-slot:expanded-item="{ headers, item }">
  <td :colspan="headers.length">Expanded Content</td>
</template>

If you want to have access to expanded items in JavaScript, don't forget to add :expanded.sync="expanded" to <v-data-table> . To open unique item on click you need to set item-key="" property on <v-data-table>.

like image 199
onurelibol Avatar answered Nov 28 '22 05:11

onurelibol