Skip to content

Commit 84e5529

Browse files
authored
refactor!: only re-render affected rows on grid selection change (#11397)
1 parent afff8b2 commit 84e5529

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,14 @@ export const SelectionMixin = (superClass) =>
111111

112112
/** @private */
113113
__selectedItemsChanged() {
114-
this.requestContentUpdate();
114+
this._getRenderedRows().forEach((row) => {
115+
if (
116+
row.hasAttribute('selected') !== this._isSelected(row._item) ||
117+
row.hasAttribute('nonselectable') !== !this.__isItemSelectable(row._item)
118+
) {
119+
this.__updateRow(row);
120+
}
121+
});
115122
}
116123

117124
/** @private */

packages/grid/test/selection.test.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,49 @@ describe('selection', () => {
7070
});
7171
});
7272

73+
it('should only re-render the affected row when selecting an item', () => {
74+
const rendererSpy = sinon.spy();
75+
grid.children[0].renderer = rendererSpy;
76+
flushGrid(grid);
77+
rendererSpy.resetHistory();
78+
79+
grid.selectItem(cachedItems[1]);
80+
81+
// Only the newly selected row should be re-rendered
82+
expect(rendererSpy).to.be.calledOnce;
83+
expect(rendererSpy.firstCall.args[2].item).to.equal(cachedItems[1]);
84+
expect(rendererSpy.firstCall.args[2].selected).to.be.true;
85+
});
86+
87+
it('should only re-render the affected row when deselecting an item', () => {
88+
const rendererSpy = sinon.spy();
89+
grid.children[0].renderer = rendererSpy;
90+
flushGrid(grid);
91+
rendererSpy.resetHistory();
92+
93+
grid.deselectItem(cachedItems[0]);
94+
95+
// Only the previously selected row should be re-rendered
96+
expect(rendererSpy).to.be.calledOnce;
97+
expect(rendererSpy.firstCall.args[2].item).to.equal(cachedItems[0]);
98+
expect(rendererSpy.firstCall.args[2].selected).to.be.false;
99+
});
100+
101+
it('should only re-render affected rows when replacing selectedItems', () => {
102+
const rendererSpy = sinon.spy();
103+
grid.children[0].renderer = rendererSpy;
104+
flushGrid(grid);
105+
rendererSpy.resetHistory();
106+
107+
// Replace selection: deselect item 0, select item 1
108+
grid.selectedItems = [cachedItems[1]];
109+
110+
expect(rendererSpy).to.be.calledTwice;
111+
const renderedItems = rendererSpy.getCalls().map((call) => call.args[2].item);
112+
expect(renderedItems).to.include(cachedItems[0]);
113+
expect(renderedItems).to.include(cachedItems[1]);
114+
});
115+
73116
it('should not update selected attribute for hidden rows', () => {
74117
grid.size = 0;
75118
grid.selectedItems = [];

0 commit comments

Comments
 (0)