Skip to content

Commit 2b9c05f

Browse files
DiegoCardosoclaude
andauthored
fix: defer setSelectedCellAndRange until sheet layout is ready (#9373)
<!-- Why --> Follow-up to #9333. The connector's `setSelectedCellAndRange` silently dropped calls when the sheet widget's `definedRowHeights` wasn't yet populated, on the assumption that Flow would reissue the call. That assumption only holds for the reload cycle path (`initialSheetSelection` set on the server, then `onSheetScroll` from the client triggering `reloadCurrentSelection`). For any other path — most notably the selection RPC sent when the user types a range into the address field — there is no reissue, so a call that loses the race against GWT's deferred initial relayout is lost permanently. This caused the cherry-pick PRs (#9365, #9366, #9367) to consistently fail 20 selection-related tests (`NavigationIT`, `NamedRangeIT`, `ChartsIT`, `SheetTabSheetIT`, `PreserveOnRefreshIT`, and the new `SpreadsheetDialogIT`). The original PR happened to pass on main's CI agent timing, but the failure is deterministic on the cherry-pick branches' GWT 2.9 / older-Flow-SNAPSHOT environment. <!-- Changes --> Queue the latest call as `_pendingSelection` and poll `definedRowHeights` every 10 ms until it's set or the element is disconnected. Rapid successive calls collapse to the final selection (the array is overwritten, only one retry loop runs at a time). Follow-up to #9333. --- 🤖 Generated with Claude Code Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ef7ccb8 commit 2b9c05f

1 file changed

Lines changed: 28 additions & 5 deletions

File tree

  • vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/resources/META-INF/resources/frontend/vaadin-spreadsheet

vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/resources/META-INF/resources/frontend/vaadin-spreadsheet/vaadin-spreadsheet.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,37 @@ export class VaadinSpreadsheet extends LitElement {
366366

367367
setSelectedCellAndRange(name, col, row, c1, c2, r1, r2, scroll) {
368368
this._flush();
369-
// The sheet widget's initial relayout is deferred via GWT's scheduler.
370-
// If this RPC runs in the same task as the initial property batch (e.g.
371-
// opening a Dialog that contains the Spreadsheet), `$scrollAreaIntoView`
372-
// would dereference `definedRowHeights` before it exists. The server
373-
// reissues this call once the spreadsheet has fully attached.
369+
// The sheet widget's initial relayout is deferred via GWT's scheduler,
370+
// so `definedRowHeights` may not yet exist when this RPC arrives in the
371+
// same task as the initial property batch (e.g. opening a Dialog that
372+
// contains the Spreadsheet). Calling `setSelectedCellAndRange` before
373+
// it's populated would throw inside `$scrollAreaIntoView`. Re-queue the
374+
// call until the layout state is ready; only the latest pending call is
375+
// kept so rapid successive calls collapse to the final selection.
374376
if (!this.api.spreadsheetWidget.sheetWidget.definedRowHeights) {
377+
this._pendingSelection = [name, col, row, c1, c2, r1, r2, scroll];
378+
if (!this._pendingSelectionScheduled) {
379+
this._pendingSelectionScheduled = true;
380+
const applyPending = () => {
381+
if (!this.isConnected || !this._pendingSelection) {
382+
this._pendingSelectionScheduled = false;
383+
this._pendingSelection = null;
384+
return;
385+
}
386+
if (this.api.spreadsheetWidget.sheetWidget.definedRowHeights) {
387+
const args = this._pendingSelection;
388+
this._pendingSelection = null;
389+
this._pendingSelectionScheduled = false;
390+
this.api.setSelectedCellAndRange(...args);
391+
return;
392+
}
393+
setTimeout(applyPending, 10);
394+
};
395+
setTimeout(applyPending, 10);
396+
}
375397
return;
376398
}
399+
this._pendingSelection = null;
377400
this.api.setSelectedCellAndRange(name, col, row, c1, c2, r1, r2, scroll);
378401
}
379402

0 commit comments

Comments
 (0)