Skip to content

Commit 77785a3

Browse files
authored
fix: reset cell order according to order of columns in DOM (#11522)
## Description Since #10632 reordering columns per drag and drop physically reorders cells instead of applying an order through CSS. Note that this does not actually reorder the columns in the DOM, so it only establishes a new "visual order". When changing the order of columns in the DOM afterwards programmatically, `_renderColumnTree` will recreate rows with the correct cell order, and `_updateOrders` will reset the `_order` property to be in sync with the DOM order again. When setting a column order in the Flow component, it will reorder columns in the DOM, which triggers the path above. However, if the order of columns in the DOM already match the new order, this path would not trigger. For that the Flow component additionally calls `_updateOrders`, which is not effective anymore as it only updates the `_order` prop, but doesn't reorder cells to reset the visual order. The use case is basically: - User reorders columns - Then clicks a button to restore initial column order - DOM order doesn't actually change, cells are neither regenerated or reordered In order to fix this, this adds a `_resetColumnOrder` method that the Flow component can use to force reset the visual order to the DOM order. The method force recreates the column tree, similar to what would happen when the column DOM order actually changes. The method also short-circuits when the visual and DOM order are already in sync. This works for the Flow component, as the mutation observer / column tree update debouncer run before the `executeJs` call, so the Flow component should be able to call this unconditionally without having to detect whether column order actually changed. Part of vaadin/flow-components#9119 ## Type of change - Bugfix
1 parent ff1f9ff commit 77785a3

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

packages/grid/src/vaadin-grid-column-reordering-mixin.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,36 @@ export const ColumnReorderingMixin = (superClass) =>
337337
updateColumnOrders(columnTree[0], this._orderBaseScope, 0);
338338
}
339339

340+
/**
341+
* Resets the visual column order so that cells in every row reflect the
342+
* current DOM order of `<vaadin-grid-column>` elements.
343+
*
344+
* Intended to be called by Vaadin Flow's `GridColumnOrderHelper` (via
345+
* `executeJs`) to realign cell order with the column DOM order after an
346+
* earlier drag reorder, even when the column DOM order itself has not
347+
* changed (in which case the `_columnTree` observer does not fire and
348+
* `_renderColumnTree` does not re-render the rows).
349+
*
350+
* @private
351+
*/
352+
_resetColumnOrder() {
353+
if (this._columnTree === undefined) {
354+
return;
355+
}
356+
357+
// Each `_columnTree[level]` array is already in DOM order. If every
358+
// level's `_order` values are monotonically non-decreasing along that
359+
// array, cells are already in sync with DOM order and no work is needed.
360+
const alreadyInDomOrder = this._columnTree.every((level) =>
361+
level.every((column, i) => i === 0 || column._order >= level[i - 1]._order),
362+
);
363+
if (alreadyInDomOrder) {
364+
return;
365+
}
366+
367+
this._columnTree = this._getColumnTree();
368+
}
369+
340370
/**
341371
* @param {!GridColumn} column
342372
* @param {string} status

packages/grid/test/column-reordering.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,26 @@ describe('reordering simple grid', () => {
435435
expect(e.detail.columns.map((column) => column.getAttribute('index'))).to.eql(['2', '1', '3', '4']);
436436
});
437437

438+
it('should restore cell order to match column DOM order when _resetColumnOrder is called', () => {
439+
// Drag the first column over the last column so cells are reordered to [2, 3, 4, 1]
440+
dragOver(headerContent[0], headerContent[3]);
441+
flushGrid(grid);
442+
expectVisualOrder(grid, [2, 3, 4, 1]);
443+
444+
// Simulate the Flow component calling _resetColumnOrder to restore the order of cells
445+
// to match the DOM order of the <vaadin-grid-column> elements, which hasn't changed.
446+
grid._resetColumnOrder();
447+
flushGrid(grid);
448+
expectVisualOrder(grid, [1, 2, 3, 4]);
449+
});
450+
451+
it('should skip DOM work in _resetColumnOrder when cells already match DOM order', () => {
452+
const spy = sinon.spy(grid, '_renderColumnTree');
453+
grid._resetColumnOrder();
454+
flushGrid(grid);
455+
expect(spy.called).to.be.false;
456+
});
457+
438458
describe('focus button mode', () => {
439459
beforeEach(() => {
440460
grid = fixtureSync(`

0 commit comments

Comments
 (0)