fix: wait for DOM updates before scrolling to expanded tree row#680
fix: wait for DOM updates before scrolling to expanded tree row#680spike-rabbit wants to merge 1 commit intosiemens:mainfrom
Conversation
Replace queueMicrotask with setTimeout when recursively scrolling to a tree row that required ancestor expansion. Microtasks run before Angular's zoneless change detection has flushed the new rows to the DOM, so the scroll container's scrollHeight is still the pre-expansion value and the browser clamps scrollTop. Deferring via setTimeout lets the DOM grow first so the scroll lands on the freshly rendered row.
There was a problem hiding this comment.
Code Review
This pull request replaces queueMicrotask with setTimeout in the scrollToRowTree method to ensure Angular has completed DOM updates before scrolling occurs. It also includes a new test case to verify scrolling behavior when expanding large tree structures. A review comment suggests adding a safety check to verify the component is still connected to the DOM within the setTimeout callback to avoid potential errors if the component is destroyed before the task executes.
There was a problem hiding this comment.
Pull request overview
Fixes DatatableComponent.scrollToRow in tree mode so scrolling occurs after ancestor expansion has actually updated the rendered viewport, preventing the browser from clamping scrollTop to the pre-expansion max.
Changes:
- Defer the recursive
scrollToRowTreecall withsetTimeoutinstead ofqueueMicrotaskafter expanding ancestors. - Update the existing tree-mode scrolling unit test to await the deferred scroll via
vi.waitFor. - Add a new unit test covering the “scroll past pre-expansion scrollHeight” scenario (many children revealed after expansion).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| projects/ngx-datatable/src/lib/components/datatable.component.ts | Changes scheduling of the post-expansion recursive scroll to run after DOM/render updates. |
| projects/ngx-datatable/src/lib/components/body/client-side-scrolling.spec.ts | Updates tree-mode scroll test synchronization and adds a regression test for large expansion + scroll clamping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What kind of change does this PR introduce? (check one with "x")
What is the current behavior?
When
scrollToRowis called on a tree row whose ancestors are still collapsed, the datatable expands the ancestors and then schedules the recursive scroll call as a microtask viaqueueMicrotask. Microtasks run before Angular's zoneless change detection has flushed the newly visible rows to the DOM, so the scroll container'sscrollHeightis still the pre-expansion value. The browser clampsscrollTopto the old maximum and the target row is not actually scrolled into view, especially when the tree grows enough that the target lies beyond the previous scrollable area.What is the new behavior?
The recursive scroll call is deferred via
setTimeoutinstead ofqueueMicrotask. This lets Angular's change detection cycle run and update the DOM (including the scroller's height) before the scroll position is computed and applied, so the browser no longer clampsscrollTopand the target row ends up at the requested position.A new unit test in
client-side-scrolling.spec.tsreproduces the failure mode: it expands a parent with 30 children inside a constrained viewport and asserts that the resultingscrollTopmatches the freshly rendered target row's offset. The test fails withqueueMicrotaskand passes withsetTimeout. The existingshould call expandToRow for a non-visible child rowtest was updated to usevi.waitForso it correctly awaits the deferred scroll.Does this PR introduce a breaking change? (check one with "x")
Other information:
None.