Skip to content

Commit 892664d

Browse files
authored
fix: prevent recurring selection attempts during drag selection (#8317)
1 parent 40e49c5 commit 892664d

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

packages/grid/src/vaadin-grid-selection-column-base-mixin.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,7 @@ export const GridSelectionColumnBaseMixin = (superClass) =>
250250
} else if (event.detail.state === 'end') {
251251
// if drag start and end stays within the same item, then toggle its state
252252
if (this.__dragStartItem) {
253-
if (this.__selectOnDrag) {
254-
this._selectItem(this.__dragStartItem);
255-
} else {
256-
this._deselectItem(this.__dragStartItem);
257-
}
253+
this.__toggleItem(this.__dragStartItem, this.__selectOnDrag);
258254
}
259255
// clear drag state after timeout, which allows preventing the
260256
// subsequent click event if drag started and ended on the same item
@@ -320,6 +316,7 @@ export const GridSelectionColumnBaseMixin = (superClass) =>
320316
if (this.__dragStartIndex === undefined) {
321317
return;
322318
}
319+
323320
// Get the row being hovered over
324321
const renderedRows = this._grid._getRenderedRows();
325322
const hoveredRow = renderedRows.find((row) => {
@@ -344,11 +341,7 @@ export const GridSelectionColumnBaseMixin = (superClass) =>
344341
(hoveredIndex > this.__dragStartIndex && row.index >= this.__dragStartIndex && row.index <= hoveredIndex) ||
345342
(hoveredIndex < this.__dragStartIndex && row.index <= this.__dragStartIndex && row.index >= hoveredIndex)
346343
) {
347-
if (this.__selectOnDrag) {
348-
this._selectItem(row._item);
349-
} else {
350-
this._deselectItem(row._item);
351-
}
344+
this.__toggleItem(row._item, this.__selectOnDrag);
352345
this.__dragStartItem = undefined;
353346
}
354347
});
@@ -430,6 +423,14 @@ export const GridSelectionColumnBaseMixin = (superClass) =>
430423
* @private
431424
*/
432425
__toggleItem(item, selected = !this._grid._isSelected(item)) {
426+
if (selected === this._grid._isSelected(item)) {
427+
// Skip selection if the item is already in the desired state.
428+
// Note, _selectItem and _deselectItem may be overridden in custom
429+
// selection column implementations, and calling them unnecessarily
430+
// might affect performance (e.g. vaadin-grid-flow-selection-column).
431+
return;
432+
}
433+
433434
if (selected) {
434435
this._selectItem(item);
435436
} else {

packages/grid/test/selection.common.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,25 @@ describe('multi selection column', () => {
689689
expect(grid.selectedItems).to.eql(grid.items.slice(1, 4));
690690
});
691691

692+
it('should not attempt to select item on mouse drag if it is already selected', () => {
693+
const selectItemSpy = sinon.spy(selectionColumn, '_selectItem');
694+
695+
const row0cell = getBodyCellContent(grid, 0, 0);
696+
const row1cell = getBodyCellContent(grid, 1, 0);
697+
698+
grid.selectedItems = [rows[1]._item];
699+
700+
fireTrackEvent(row0cell, row0cell, 'start');
701+
clock.tick(10);
702+
fireTrackEvent(row1cell, row0cell, 'track');
703+
clock.tick(10);
704+
fireTrackEvent(row1cell, row0cell, 'end');
705+
clock.tick(10);
706+
707+
expect(selectItemSpy).to.be.calledOnce;
708+
expect(selectItemSpy.args[0][0]).to.not.equal('1');
709+
});
710+
692711
it('should not select any items on mouse drag when dragSelect is disabled', () => {
693712
selectionColumn.dragSelect = false;
694713

@@ -775,6 +794,25 @@ describe('multi selection column', () => {
775794
expect(grid.selectedItems).to.empty;
776795
});
777796

797+
it('should not attempt to deselect item on mouse drag if it is already deselected', () => {
798+
const deselectItemSpy = sinon.spy(selectionColumn, '_deselectItem');
799+
800+
const row0cell = getBodyCellContent(grid, 0, 0);
801+
const row1cell = getBodyCellContent(grid, 1, 0);
802+
803+
grid.selectedItems = [rows[0]._item];
804+
805+
fireTrackEvent(row0cell, row0cell, 'start');
806+
clock.tick(10);
807+
fireTrackEvent(row1cell, row0cell, 'track');
808+
clock.tick(10);
809+
fireTrackEvent(row1cell, row0cell, 'end');
810+
clock.tick(10);
811+
812+
expect(deselectItemSpy).to.be.calledOnce;
813+
expect(deselectItemSpy.args[0][0]).to.not.equal('1');
814+
});
815+
778816
it('should prevent text selection on mouse dragging', () => {
779817
const spy = sinon.spy();
780818
const sourceCell = getBodyCellContent(grid, 0, 0);

0 commit comments

Comments
 (0)