Skip to content

Commit c9a2a22

Browse files
committed
feat(VDataTable): support shift click for multiple selection
resolves #20055
1 parent acff32f commit c9a2a22

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

packages/vuetify/src/components/VDataTable/VDataTableRow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export const VDataTableRow = genericComponent<new <T>(
143143
<VCheckboxBtn
144144
disabled={ !item.selectable }
145145
modelValue={ isSelected([item]) }
146-
onClick={ withModifiers(() => toggleSelect(item), ['stop']) }
146+
onClick={ withModifiers(event => toggleSelect(item, props.index, event as MouseEvent), ['stop']) }
147147
/>
148148
)
149149
}

packages/vuetify/src/components/VDataTable/composables/select.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { useProxiedModel } from '@/composables/proxiedModel'
33

44
// Utilities
5-
import { computed, inject, provide } from 'vue'
5+
import { computed, inject, provide, ref, shallowRef } from 'vue'
66
import { deepEqual, propsFactory, wrapInArray } from '@/util'
77

88
// Types
@@ -122,6 +122,8 @@ export function provideSelection (
122122
}
123123
})
124124

125+
const lastSelectedIndex = shallowRef<number | null>(null)
126+
125127
function isSelected (items: SelectableItem | SelectableItem[]) {
126128
return wrapInArray(items).every(item => selected.value.has(item.value))
127129
}
@@ -140,8 +142,20 @@ export function provideSelection (
140142
selected.value = newSelected
141143
}
142144

143-
function toggleSelect (item: SelectableItem) {
144-
select([item], !isSelected([item]))
145+
function toggleSelect (item: SelectableItem, index?: number, event?: MouseEvent) {
146+
const items = []
147+
index = index ?? allItems.value.findIndex(i => i.value === item.value)
148+
149+
if (props.selectStrategy !== 'single' && event?.shiftKey && lastSelectedIndex.value !== null) {
150+
const [start, end] = [lastSelectedIndex.value, index].sort((a, b) => a - b)
151+
152+
items.push(...allItems.value.slice(start, end + 1))
153+
} else {
154+
items.push(item)
155+
lastSelectedIndex.value = index
156+
}
157+
158+
select(items, !isSelected([item]))
145159
}
146160

147161
function selectAll (value: boolean) {
@@ -174,6 +188,8 @@ export function provideSelection (
174188
someSelected,
175189
allSelected,
176190
showSelectAll,
191+
lastSelectedIndex,
192+
selectStrategy,
177193
}
178194

179195
provide(VDataTableSelectionSymbol, data)

0 commit comments

Comments
 (0)