Skip to content

Commit da49558

Browse files
authored
fix(table): fix range selection (#2865)
1 parent 8570c96 commit da49558

File tree

6 files changed

+208
-63
lines changed

6 files changed

+208
-63
lines changed

src/components/table/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,16 @@ as read-only.**
11881188
<!-- b-table-selectable.vue -->
11891189
```
11901190

1191+
When table is selectable, it will have class `b-table-selectable`, and one of the following three
1192+
classes (depending on which mode is in use), on the `<table>` element:
1193+
1194+
- `b-table-select-single`
1195+
- `b-table-select-multi`
1196+
- `b-table-select-range`
1197+
1198+
When at least one row is selected the class `b-table-selecting` will be active on the `<table>`
1199+
element.
1200+
11911201
**Notes:**
11921202

11931203
- _Paging, filtering, or sorting will clear the selection. The `row-selected` event will be emitted

src/components/table/_table.scss

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,15 @@
159159
}
160160

161161
/* b-table: selectable rows */
162-
table.b-table.b-table-selectable > tbody > tr {
163-
cursor: pointer;
164-
// user-select: none;
162+
.b-table.table.b-table-selectable {
163+
& > tbody > tr {
164+
cursor: pointer;
165+
}
166+
167+
&.b-table-selecting {
168+
// Disabled text-selection when in mode range when at least one row selected
169+
&.b-table-select-range > tbody > tr {
170+
user-select: none;
171+
}
172+
}
165173
}

src/components/table/helpers/mixin-selectable.js

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import looseEqual from '../../../utils/loose-equal'
2-
import { isArray } from '../../../utils/array'
2+
import { isArray, arrayIncludes } from '../../../utils/array'
33
import sanitizeRow from './sanitize-row'
44

55
export default {
@@ -23,6 +23,29 @@ export default {
2323
selectedLastRow: -1
2424
}
2525
},
26+
computed: {
27+
selectableTableClasses() {
28+
const selectable = this.selectable
29+
const isSelecting = selectable && this.selectedRows && this.selectedRows.some(Boolean)
30+
return {
31+
'b-table-selectable': selectable,
32+
[`b-table-select-${this.selectMode}`]: selectable,
33+
'b-table-selecting': isSelecting
34+
}
35+
},
36+
selectableTableAttrs() {
37+
return {
38+
'aria-multiselectable': this.selectableIsMultiSelect
39+
}
40+
},
41+
selectableIsMultiSelect() {
42+
if (this.selectable) {
43+
return arrayIncludes(['range', 'multi'], this.selectMode) ? 'true' : 'false'
44+
} else {
45+
return null
46+
}
47+
}
48+
},
2649
watch: {
2750
computedItems(newVal, oldVal) {
2851
// Reset for selectable
@@ -72,17 +95,18 @@ export default {
7295
isRowSelected(idx) {
7396
return Boolean(this.selectedRows[idx])
7497
},
75-
rowSelectedClasses(idx) {
76-
if (this.selectable) {
77-
const rowSelected = this.isRowSelected(idx)
78-
const base = this.dark ? 'bg' : 'table'
79-
const variant = this.selectedVariant
80-
return {
81-
'b-row-selected': rowSelected,
82-
[`${base}-${variant}`]: rowSelected && variant
83-
}
84-
} else {
85-
return {}
98+
selectableRowClasses(idx) {
99+
const rowSelected = this.isRowSelected(idx)
100+
const base = this.dark ? 'bg' : 'table'
101+
const variant = this.selectedVariant
102+
return {
103+
'b-table-row-selected': this.selectable && rowSelected,
104+
[`${base}-${variant}`]: this.selectable && rowSelected && variant
105+
}
106+
},
107+
selectableRowAttrs(idx) {
108+
return {
109+
'aria-selected': !this.selectable ? null : this.isRowSelected(idx) ? 'true' : 'false'
86110
}
87111
},
88112
clearSelected() {
@@ -125,7 +149,6 @@ export default {
125149
idx <= Math.max(this.selectedLastRow, index);
126150
idx++
127151
) {
128-
// this.$set(this.selectedRows, idx, true)
129152
selectedRows[idx] = true
130153
}
131154
selected = true
@@ -138,7 +161,6 @@ export default {
138161
this.selectedLastRow = selected ? index : -1
139162
}
140163
}
141-
// this.$set(this.selectedRows, index, selected)
142164
selectedRows[index] = selected
143165
this.selectedRows = selectedRows
144166
}

src/components/table/helpers/mixin-tbody-row.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ export default {
195195
const hasRowClickHandler = this.$listeners['row-clicked'] || this.selectable
196196
const $detailsSlot = $scoped['row-details']
197197
const rowShowDetails = Boolean(item._showDetails && $detailsSlot)
198-
const rowSelected = this.isRowSelected(rowIndex) /* from selctable mixin */
199198

200199
// We can return more than one TR if rowDetails enabled
201200
const $rows = []
@@ -244,7 +243,7 @@ export default {
244243
key: `__b-table-row-${rowKey}__`,
245244
class: [
246245
this.rowClasses(item),
247-
this.rowSelectedClasses(rowIndex),
246+
this.selectableRowClasses(rowIndex),
248247
{
249248
'b-table-has-details': rowShowDetails
250249
}
@@ -256,8 +255,8 @@ export default {
256255
'aria-describedby': detailsId,
257256
'aria-owns': detailsId,
258257
'aria-rowindex': ariaRowIndex,
259-
'aria-selected': this.selectable ? (rowSelected ? 'true' : 'false') : null,
260-
role: 'row'
258+
role: 'row',
259+
...this.selectableRowAttrs(rowIndex)
261260
},
262261
on: {
263262
// TODO: only instatiate handlers if we have registered listeners (except row-clicked)

0 commit comments

Comments
 (0)