Skip to content

fix(grid): fix zone.onStable patterns broken in zoneless change detection - 22.0.x#17386

Open
viktorkombov wants to merge 2 commits into
22.0.xfrom
vkombov/grid-zoneless-issues-22.0.x
Open

fix(grid): fix zone.onStable patterns broken in zoneless change detection - 22.0.x#17386
viktorkombov wants to merge 2 commits into
22.0.xfrom
vkombov/grid-zoneless-issues-22.0.x

Conversation

@viktorkombov

@viktorkombov viktorkombov commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Closes #17364
Closes #17385
Closes #17318
Closes #17280

What

Grid virtualization, autosizing, and keyboard navigation relied on NgZone.onStable, which never emits in zoneless apps. As a result, scroll-driven chunkLoad, column autosize, filter-row rendering, and post-scroll cell activation silently never ran.

This migrates all of that off onStable and onto Angular’s render hooks.

Changes

Core

  • Added a new central helper: runAfterRenderOnce(injector, cb, phase?) in core/utils.ts.

    • This is now the single scheduling point for all deferred-render work.
    • Previously, this logic was scattered across onStable / ɵNoopNgZone branches.
  • Updated every affected call site to go through runAfterRenderOnce.

  • Removed the private ɵNoopNgZone-based zoneless detection.

  • Removed the duplicated per-class runAfterRender helpers.

Grids

  • IgxFilteringService.isFilterRowVisible is now signal-backed, so the OnPush header row re-renders without requiring a zone tick.
  • Filter cells now observe their own size via ResizeObserver to recompute visible chips after resize.
  • Column resize now explicitly notifies the grid via notifyResized, instead of relying on an empty zone.run.
  • Keyboard navigation now notifies after any scrolling navigation key, not just Ctrl.
  • Hierarchical navigation now subscribes to chunkLoad before scrolling, avoiding missed synchronous emissions.
  • Deferred work in for_of, grid-base, and pivot-grid was migrated to runAfterRenderOnce.

Tests

  • Added zoneless duplicates using provideZonelessChangeDetection for the affected grid, tree, hierarchical, and pivot suites.

  • Centralized async test helpers in helper-utils.spec.ts.

  • runAfterRenderOnce consumers now settle through shared helpers:

    • waitForGridSettle
    • setGridVerticalScrollTop
    • dispatchGridScrollEvents
    • navigateWithGridScroll
  • Updated the zoned originals to await the new render-boundary timing.

    • Previously, they happened to align with onStable.

Notes

  • Behavior for zoned apps is unchanged in practice.

    • Real interaction still triggers a render.
    • Only the timing signal moved from onStable to afterNextRender.
  • No runOutsideAngular was removed.

  • No forced detectChanges was added in zoneless tests.

Motivation / Context

Type of Change (check all that apply):

  • Bug fix
  • New functionality
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactoring (no functional changes)
  • Documentation
  • Demos
  • CI/CD
  • Tests
  • Changelog
  • Skills/Agents

Component(s) / Area(s) Affected:

How Has This Been Tested?

  • Unit tests
  • Manual testing
  • Automated e2e tests

Test Configuration:

  • Angular version:
  • Browser(s):
  • OS:

Screenshots / Recordings

Checklist:

  • All relevant tags have been applied to this PR
  • This PR includes unit tests covering all the new code (test guidelines)
  • This PR includes API docs for newly added methods/properties (api docs guidelines)
  • This PR includes feature/README.MD updates for the feature docs
  • This PR includes general feature table updates in the root README.MD
  • This PR includes CHANGELOG.MD updates for newly added functionality
  • This PR contains breaking changes
  • This PR includes ng update migrations for the breaking changes (migrations guidelines)
  • This PR includes behavioral changes and the feature specification has been updated with them
  • Accessibility (ARIA, keyboard navigation, focus management) has been verified

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

This PR fixes multiple Grid (and related) behaviors that previously relied on NgZone.onStable as a post-render scheduling signal, which does not emit under Angular’s zoneless change detection. It replaces those onStable patterns with render-bound scheduling and adds zoneless regression coverage across grid, hierarchical grid, tree grid, pivot grid, and for-of virtualization paths.

Changes:

  • Introduces runAfterRenderOnce(injector, cb, phase?) (core) and migrates deferred work from NgZone.onStable to afterNextRender across grid/virtualization/autosize/navigation code paths.
  • Updates grid behaviors to better notify/refresh in zoneless mode (e.g., signal-backed filter-row visibility, resize-driven chip recalculation, explicit resize notifications, keyboard navigation scroll activation).
  • Adds/updates extensive unit tests and shared async helpers, including new zoneless-spec variants using provideZonelessChangeDetection().

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
projects/igniteui-angular/test-utils/helper-utils.spec.ts Adds shared async helpers for scroll/navigation settling and zoneless-friendly scroll detection.
projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.spec.ts Adjusts invalid sample test setup to use an empty FilteringExpressionsTree.
projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.spec.ts Adds zoneless auto-generated-columns coverage; updates timing awaits.
projects/igniteui-angular/grids/tree-grid/src/tree-grid-summaries.spec.ts Adds zoneless runtime summary-settings test coverage; updates settling awaits.
projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts Refactors scroll-driven navigation waits; adds zoneless navigation suite.
projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts Migrates post-render dimension autosizing from onStable to runAfterRenderOnce.
projects/igniteui-angular/grids/pivot-grid/src/pivot-grid-keyboard-nav.spec.ts Uses settle helper to avoid fixed-delay races in virtualization navigation tests.
projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.virtualization.spec.ts Improves scroll settling using shared helpers; adds a zoneless virtualization suite.
projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts Refactors navigation tests to settle scroll/render deterministically; adds zoneless coverage.
projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid-navigation.service.ts Subscribes to chunkLoad before scrolling to avoid missing synchronous emissions.
projects/igniteui-angular/grids/grid/src/grid.zoneless.spec.ts Adds a new zoneless regression spec suite for core grid scenarios.
projects/igniteui-angular/grids/grid/src/grid.search.spec.ts Adds zoneless search+grouping coverage and improves scroll/chunkLoad synchronization.
projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts Refactors scroll-driven activation waits; adds zoneless master-detail navigation coverage.
projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts Adds zoneless regression coverage for horizontal virtualization state restoration.
projects/igniteui-angular/grids/grid/src/grid.component.spec.ts Replaces fixed delays with settle helper; adds zoneless aria-attribute regression coverage.
projects/igniteui-angular/grids/grid/src/grid-mrl-keyboard-nav.spec.ts Uses shared navigation-with-scroll helper; adds zoneless MRL navigation scenarios.
projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts Improves zoned timing comments and adds zoneless keyboard-navigation coverage for virtual grids.
projects/igniteui-angular/grids/grid/src/grid-keyBoardNav-headers.spec.ts Reworks tests away from fakeAsync where afterNextRender is involved; adds zoneless header navigation tests.
projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts Adds zoneless filtering-row UI coverage and adjusts resize interactions/waits.
projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts Uses settle helper for scroll-driven selection; adds zoneless selection regression coverage.
projects/igniteui-angular/grids/grid/src/grid-base.directive.ts Migrates multiple onStable-based paths to runAfterRenderOnce; removes NoopNgZone detection; hardens navigation callback invocation.
projects/igniteui-angular/grids/grid/src/column.spec.ts Fixes minor statement issues; adds zoneless date/time editor-format regression coverage.
projects/igniteui-angular/grids/grid/src/column-group.spec.ts Makes width assertions more robust (pixel tolerance); adds zoneless width regression coverage.
projects/igniteui-angular/grids/core/src/resizing/resizing.service.ts Notifies grid after pointer-resize via post-render scheduling to support zoneless.
projects/igniteui-angular/grids/core/src/grid-navigation.service.ts Expands scroll-notification logic for keyboard navigation (not just ctrl-modified keys).
projects/igniteui-angular/grids/core/src/filtering/grid-filtering.service.ts Makes isFilterRowVisible signal-backed to trigger OnPush template updates in zoneless mode.
projects/igniteui-angular/grids/core/src/filtering/base/grid-filtering-cell.component.ts Observes filter-cell size changes and marks for check so chip visibility recomputes after resizes.
projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts Replaces onStable/afterNextRender scattered logic with runAfterRenderOnce; fixes reduce initial value.
projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts Adds zoneless virtualization sizing regression tests for for-of scroll recalculation.
projects/igniteui-angular/core/src/core/utils.ts Introduces runAfterRenderOnce helper (afterNextRender wrapper) as the central deferred-render scheduler.
projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts Replaces fixed timer waits with a deterministic childrenResolved event await.

Comment thread projects/igniteui-angular/grids/grid/src/grid.zoneless.spec.ts Outdated
Comment thread projects/igniteui-angular/grids/grid/src/grid.zoneless.spec.ts Outdated
Comment thread projects/igniteui-angular/grids/grid/src/grid.zoneless.spec.ts Outdated
Comment thread projects/igniteui-angular/grids/grid/src/grid.zoneless.spec.ts Outdated
@viktorkombov viktorkombov added ❌ do not merge and removed ❌ status: awaiting-test PRs awaiting manual verification labels Jul 6, 2026
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