Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select all rows of a Vuetify data table with custom table body implementation

I can't figure how to implement the select all option for my data-table using Vuetify v2 when I have a custom implementation for the slot body.

Here is a little example:

<template>
  <v-card
    max-width="300"
    class="pa-6"
  >
    <v-data-table
      :items="tasks"
      :headers="headers"
      show-select
      dense
    >
      <template v-slot:body="{ items }">
        <tbody>
          <tr
            v-for="item in items"
            :key="item.id"
          >
            <td>
              <v-checkbox
                v-model="selectedTasks"
                :value="item.id"
                style="margin:0px;padding:0px"
                hide-details
              />
            </td>
            <td>{{ item.text }}</td>
            <td>
              <v-btn
                text
                icon
                x-small
              >
                <v-icon>pageview</v-icon>
              </v-btn>
            </td>
          </tr>
        </tbody>
      </template>
    </v-data-table>
  </v-card>
</template>
<script>
export default {
  data() {
    return {
      headers: [
        { text: 'task', value: 'text' },
        { text: 'actions' }
      ],
      selectedTasks: []
    }
  },
  computed: {
    tasks() {
      return [
        { id: 1, text: 'Collect packets' },
        { id: 2, text: 'Buy bread' }
      ]
    }
  }
}
</script>

Which produces the following data table:

enter image description here

Now I want to implement that when the checkbox "all" is selected (like above in the picture), it selects all the rows of my table.

The doc says to implement the slot header.data-table-select to customise the select all button, and I could find the example below in the examples about slots for the data-table.

<template v-slot:header.data-table-select="{ on , props }">
    <v-simple-checkbox
       color="purple"
       v-bind="props"
       v-on="on"
    />
</template>

However, I can't make it to select all the rows when I check this box. I didn't find any example on how to implement the select all with a "custom" table body. Hopefully, someone can help me here. Thanks in advance

like image 499
skuallpa Avatar asked Aug 27 '19 08:08

skuallpa


1 Answers

Data table v-model needs to be set to selectedItems and check box for selecting needs to have value of item collection.

<!DOCTYPE html>
<html>

<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>

<body>
<div id="app">
    <v-app>
        <v-content>
            <v-container>
                <h2>Data Table</h2>

                <v-data-table v-model="selectedTasks" :headers="headers" :items="tasks" item-key="id" show-select>

                    <template v-slot:body="{ items }">
                        <tbody>
                            <tr v-for="item in items" :key="item.id">
                                <td>
                                    <v-checkbox v-model="selectedTasks" :value="item" style="margin:0px;padding:0px"
                                        hide-details />
                                </td>
                                <td>{{ item.text }}</td>
                                <td>
                                    <v-btn text icon x-small>
                                        Edit
                                    </v-btn>
                                </td>
                            </tr>
                        </tbody>
                    </template>
                </v-data-table>
                <v-btn v-on:click="addTask()">Add Task</v-btn>
            </v-container>
        </v-content>
    </v-app>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<script>
    new Vue({
        el: '#app',
        vuetify: new Vuetify(),

        data() {
            return {
                headers: [
                    {
                        text: 'Task',
                        value: 'text'
                    },
                    {
                        text: 'Actions'
                    }
                ],
                tasks: [
                    {
                        id: 1,
                        text: 'Collect packets'
                    },
                    {
                        id: 2,
                        text: 'Buy bread'
                    }
                ],
                selectedTasks: []
            }
        },
        methods: {
            addTask() {
                this.tasks = this.tasks.map(t => ({...t}))
                this.tasks.push({id: this.tasks.length + 1, text: 'New Task'});

                this.selectedTasks = this.selectedTasks.map(t => {
                    return this.tasks.find(e => e.id == t.id) || t;
                })
            }
        }
    })
</script>
</body>

</html>
like image 162
Edin Omeragic Avatar answered Oct 21 '22 15:10

Edin Omeragic