Skip to content

fix(grid): restore trailing scroll emission so top rows aren't lost after fast scroll - 21.2.x#17460

Open
Zneeky wants to merge 3 commits into
21.2.xfrom
aahmedov/fix-grid-scroll-trailing-21.2.x
Open

fix(grid): restore trailing scroll emission so top rows aren't lost after fast scroll - 21.2.x#17460
Zneeky wants to merge 3 commits into
21.2.xfrom
aahmedov/fix-grid-scroll-trailing-21.2.x

Conversation

@Zneeky

@Zneeky Zneeky commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Closes #17287

Description

Fixes a regression where the top rows of igx-grid / igx-tree-grid /
igx-hierarchical-grid could become invisible after a fast momentum/inertia
scroll back to the top. The scrollbar reports scrollTop ≈ 0, but the
virtualized rows stay frozen at an intermediate startIndex (~row 10–15).

The vertical-scroll throttle on scrollNotify was passing no config, so it
used RxJS's default { leading: true, trailing: false }. The trailing edge
is what guarantees the final settle position of a scroll gets processed, so
without it the last events of a momentum flick (including the scrollTop ≈ 0
settle) were dropped. Restoring { leading: true, trailing: true } fixes this
while keeping the immediate leading-edge response.

Motivation / Context

The throttle originally used
throttleTime(THROTTLE_TIME, animationFrameScheduler, { leading: false, trailing: true }).
When it was changed to a data-size–dependent throttle(durationSelector) (in
"feat(grids): Apply different throttle based on the amount of data in display"),
the config object was dropped and the operator fell back to the RxJS default
{ leading: true, trailing: false }.

Without the trailing edge, the last scroll events of a momentum flick fall inside
a throttle window (up to 60 ms for large grids) and are discarded.
verticalScrollContainer.onScroll never runs for the final position, so
virtualization stays at the last leading startIndex while the DOM scrollbar
settles at the top → the top rows appear missing.

The fix keeps leading: true (matching current master, so timing-sensitive
scroll/navigation tests are unaffected) and adds trailing: true to restore the
guarantee that the final resting scroll position is always handled — a strict
superset of the current behavior. Independent of zone/zoneless change detection.

Backported to 21.2.x and 22.0.x.

Copilot AI review requested due to automatic review settings July 24, 2026 08:53
@Zneeky Zneeky changed the title fix(grid): ensure final settle position in momentum scroll with trail… fix(grid): restore trailing scroll emission so top rows aren't lost after fast scroll - 21.2.x Jul 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression in shared grid vertical scroll handling where fast momentum/inertia scrolling could leave virtualization out of sync with the scrollbar’s final resting position, causing top rows to appear missing.

Changes:

  • Updates the scrollNotify RxJS throttling configuration to ensure the final (settling) scroll position is processed.
  • Adds inline rationale explaining why trailing scroll handling is required for virtualization correctness.

Comment thread projects/igniteui-angular/grids/grid/src/grid-base.directive.ts
Comment thread projects/igniteui-angular/grids/grid/src/grid-base.directive.ts
Drives the vertical scrollNotify stream with an intermediate (leading-edge)
position followed by a scrollTop=0 settle in the same throttle window, so the
settle can only be delivered on the trailing edge. Asserts the grid resets to
startIndex 0 / renders row 0, guarding against the dropped-trailing throttle
config that left the top rows frozen out of view.
@Zneeky
Zneeky requested a review from ChronosSF July 24, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants