isebarn
isebarn

Reputation: 3950

Vuetify 2.x: v-data-table expand row on click

I am using Vuetify.js and I am creating a a v-data-table

I cannot figure out how to expand a row by clicking anywhere on it, it seems that the only possibility is by using the show-expand property and clicking the icon

Final solution

As suggested here, the v-data-table can link an array to its expanded property, so if you push any item from the table, to this array, it will expand the corresponding row. Intuitive and smart

<template>
  <v-data-table
    :headers="headers"
    :items="items"
    :expanded="expanded"
    item-key="id"
    @click:row="expandRow"
  />
</template>

<script>
  data () {
    return {
      expanded: [],
    }
  },

  expandRow (item) {
    // would be
    // this.expanded = [item]
    // but if you click an expanded row, you want it to collapse
    this.expanded = item === this.expanded[0] ? [] : [item]
  },
</script>

Upvotes: 11

Views: 26441

Answers (4)

Taras
Taras

Reputation: 31

If you are using v-slot:item, or you set the prop :hide-default-header="true", then you can implement it this way:

<template v-slot:item="{item, index}"> 
     <tr @click="expandedIndex = expandedIndex==-1?index:-1">
       <span> {{item}} </span>  
     </tr>
   <tr :colspan="headers.length" v-if="expandedIndex==index">Expanded content</tr>
</template>

If you want to be able to expand multiple rows at the same time, you can do this:

  <v-data-table :headers="headers" :items="items">
    <template v-slot:item="{item, index}"> 
     <tr @click="expandRow(index)">
       <span> {{item}} </span>  
     </tr>
     <tr v-if="expandedRows.includes(index)">
       <td :colspan="headers.length">
            Expanded content 
       </td>
     </tr>
    </template>
 </v-data-table>

<script> 

   ...
   ...

   expandedRows=[]; 
   expandRow(index){ 
     const indexOfRow = this.expandedRows.indexOf(index)
     if(indexOfRow>-1){
       this.expandedRows.splice(indexOfRow,1);
       return;
     }
     this.expandedRows.push(index);
   }
</script> 

Upvotes: 0

Micael
Micael

Reputation: 351

It worked for me:

<v-data-table
  ...
  @click:row="(item, slot) => slot.expand(!slot.isExpanded)"
/>

Api docs here

Upvotes: 35

Zack Heisenberg
Zack Heisenberg

Reputation: 517

i am not sure if you still need this :P but i wanted to improve dreijntjens reply for people who see this post

so add a listener attr

<v-data-table
  :headers="headers"
  :items="desserts"
  :expanded="expanded"
  item-key="name"
  show-expand
  class="elevation-1"
  @click:row="clicked">

and add this method

  clicked (value) {
    const index = this.expanded.indexOf(value)
    if (index === -1) {
      this.expanded.push(value)
    } else {
      this.expanded.splice(index, 1)
    }
  },

my method will actually both expand and close on click

Upvotes: 3

dreijntjens
dreijntjens

Reputation: 4835

There is a click event which gives you the current row on the v-data-table. This one you can use. In the event you update the expanded value

Like this:

HTML:

 <div id="app">
  <v-app id="inspire">
    <v-data-table
      :headers="headers"
      :items="desserts"
      :expanded="expanded"
      item-key="name"
      show-expand
      class="elevation-1"
      @click:row="clicked">
      <template v-slot:top>
        <v-toolbar flat color="white">
          <v-toolbar-title>Expandable Table</v-toolbar-title>
          <div class="flex-grow-1"></div>
          <v-switch v-model="singleExpand" label="Single expand" class="mt-2"></v-switch>
        </v-toolbar>
      </template>
      <template v-slot:expanded-item="{ headers }">
        <td :colspan="headers.length">Peek-a-boo!</td>
      </template>
    </v-data-table>
  </v-app>
</div>

vue js:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  methods: {
    clicked(value) {
      this.expanded.push(value)
    }
},

  data () {
    return {
      expanded: ['Donut'],
      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' },
      ],
      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%',
        }
      ],
    }
  },
})

Upvotes: 16

Related Questions