When using "show-select"s in a VDataTable there is currently no native way of quickly selecting multiple, neighboring items.
e.g. If you want to select the first 15 items in a table, you have to individually click on each checkbox.
Listen for "Shift"-clicks.
Once you have marked an item, as soon as you mark another item (while holding the shift key) all the items in between will get selected as well.
For mobile devices instead of listening to shift click, you could listen to double clicks on the second item.
Here is some code, it's not perfect, but should illustrate what would be nice to have by default in the data table component.
// select everything between last 2 selected items
shiftClick(item) {
if (this.selectedItems.length >= 2) {
const secondToLastItemId = this.selectedItems[this.selectedItems.length - 2].id;
const secondToLastItemIndex = this.items
.map(rowData => rowData.id)
.indexOf(secondToLastItemId);
const lastItemIndex = this.items
.map(rowData => rowData.id)
.indexOf(item.id);
let startIndex = null;
let endIndex = null;
if (lastItemIndex > secondToLastItemIndex) {
startIndex = secondToLastItemIndex + 1;
endIndex = lastItemIndex - 1;
} else {
startIndex = lastItemIndex + 1;
endIndex = secondToLastItemIndex - 1;
}
for (let i = startIndex; i <= endIndex; i += 1) {
if (
!this.selectedItems.some(
element => element.id === this.items[i].id
)
) {
this.selectedItems.push(this.items[i]);
}
}
}
}
doubleClick(item) {
if (this.selectedItems.length !== 0) {
this.selectedItems.push(item);
this.shiftClick(item);
}
}
This feature needs more attention imo.
We actually needed a feature like this on a current project. It wasn't very tough to implement.
Making sure that text wasn't highlighted when holding shift was one part of it, adding the window listeners to see when shift was being held, and then the little method to do bulk selection kind of like what OP posted.
<template>
<v-app :class="{noselect: shiftKeyOn}">
<v-main>
<v-container>
<v-card>
<v-card-title>Shift + Click Bulk Select Demo</v-card-title>
<v-data-table
v-model="selectedRows"
@current-items="current = $event"
@item-selected="bulkSelect"
:headers="headers"
:items="desserts"
item-key="id"
class="elevation-1"
show-select
unselectable
></v-data-table>
</v-card>
</v-container>
</v-main>
</v-app>
</template>
<script>
import { desserts } from "@/mocks/data.json";
export default {
name: "App",
created() {
const self = this;
self.keyDownHandler = function ({ key }) {
if (key == "Shift") self.shiftKeyOn = true;
};
self.keyUpHandler = function ({ key }) {
if (key == "Shift") self.shiftKeyOn = false;
};
window.addEventListener("keydown", this.keyDownHandler);
window.addEventListener("keyup", this.keyUpHandler);
},
beforeDestroy() {
window.removeEventListener("keydown", this.keyDownHandler);
window.removeEventListener("keyup", this.keyUpHandler);
},
data() {
return {
shiftKeyOn: false,
current: [],
selectedRows: [],
headers: [
{ text: "ID", value: "id" },
{
text: "Dessert",
align: "left",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
desserts,
};
},
methods: {
bulkSelect({ item: b, value }) {
const { selectedRows, current, shiftKeyOn } = this;
if (selectedRows.length == 1 && value == true && shiftKeyOn) {
const [a] = selectedRows;
let start = current.findIndex((item) => item == a);
let end = current.findIndex((item) => item == b);
if (start - end > 0) {
let temp = start;
start = end;
end = temp;
}
for (let i = start; i <= end; i++) {
selectedRows.push(current[i]);
}
}
},
},
};
</script>
<style>
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
</style>
Would be cool if something like this was just built in as an attrib.
I made a toy project showing it in action.
Codepen
Demo
repo
Most helpful comment
We actually needed a feature like this on a current project. It wasn't very tough to implement.
Making sure that text wasn't highlighted when holding shift was one part of it, adding the window listeners to see when shift was being held, and then the little method to do bulk selection kind of like what OP posted.
Would be cool if something like this was just built in as an attrib.
I made a toy project showing it in action.
Codepen
Demo
repo