Skip to content

fix(grid): skip redundant sizing pass after data and column change - 21.2.x - #17802

Open
viktorkombov wants to merge 6 commits into
21.2.xfrom
vkombov/fix-17792-21.2.x
Open

viktorkombov wants to merge 6 commits into
21.2.xfrom
vkombov/fix-17792-21.2.x

Conversation

@viktorkombov

@viktorkombov viktorkombov commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Closes #17792

Description

Backport of #17801 to 21.2.x.

Replacing the data and the columns of a percentage-height grid ran three sizing passes instead of two. This is the "Data switch" slowdown reported since 21.2.12 / 22.0.4.

Problem: since #17328, calculateGridSizes() schedules a post-render check (runAfterRenderOnce) that runs the grid's ngDoCheck again. Zoneless apps depend on it. On a data and column switch, that check already sizes the grid for the new columns. Then the Promise-deferred repaints from onColumnsAddedOrRemoved() and IgxGridSummaryService.resetSummaryHeight() (one per new column) ran a third, identical sizing pass, in both zoneless and ZoneJS apps. In the benchmark's switch the fields change and removing the old columns cancels that request, but it is made again in the same pass: the new data first meets the old filters, so the vertical scrollbar hides and shows again.

Fix: the post-render check is unchanged. Those deferred repaints now go through a new internal notifyChangesAfterCurrentPass(). It drops a request only when a post-render check and a new sizing pass have both run after it; otherwise it repaints as before. The hierarchical grid publishes new columns in a Promise, so it now also requests a repaint when they replace columns of the same count; before, it relied on that summary repaint.

Motivation / Context

Fixes the regression reported in #17792. Replaying the benchmark's data-source switch with its own component, steps and mutation timer, the switch runs two sizing passes instead of three and takes about 17-25% less time, in line with reverting the width callback. Skipping the post-render width callback for explicit widths is not an option: it breaks existing zoneless tests (aria-colcount with grouped columns, last row after scrolling) and the filter chips indicator after a column resize.

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:

Grid, Tree Grid, Hierarchical Grid (shared sizing in the grid base), grid summary service

How Has This Been Tested?

  • Unit tests
  • Manual testing
  • Automated e2e tests

New IgxGrid - sizing after data and column replacement specs in grid.component.spec.ts, run zoneless (with exhaustive checkNoChanges) and with ZoneJS:

  • no duplicate sizing pass when the data and columns of a percentage-height grid are replaced, with the same fields and with new fields after filtering an old column, as in the benchmark (3 passes without the fix)
  • rendered content, virtualization and scrollbar geometry after replacing the data and columns (with the same and with new fields), with default, 100%, px and null widths
  • switching between explicit and null width, and resizing the container of a 100% grid
  • zoneless hierarchical grid: replacing the data and columns of the same count together with a width change renders and sizes the new columns (hierarchical-grid.spec.ts)

grid.component, grid-filtering-ui, grid-summary, grid.master-detail and the hierarchical grid specs pass locally.

Test Configuration:

  • Angular version: 21.2.9
  • Browser(s): Chrome Headless 155
  • OS: Windows 11

Screenshots / Recordings

N/A

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

🤖 Generated with Claude Code

The post-render width callback in calculateGridSizes re-checks the grid
after every sizing pass. When the data and columns of a percentage-height
grid are replaced, that re-check already sizes the grid for the new
columns, and the Promise-deferred repaints from onColumnsAddedOrRemoved
and resetSummaryHeight then ran a third, identical sizing pass.

Route those repaints through notifyChangesAfterCurrentPass, which drops
the request once a post-render check and a new sizing pass have run
after it.

Closes #17792

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 19, 2026 19:30

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.

🔵 Needs a closer look

Shared render timing needs browser validation across both change-detection modes, with replacement tests exercising the column-add/remove path.

1 open issue
What changed in this PR

Backports #17801 to 21.2.x to reduce redundant grid sizing after data and column replacement, addressing #17792.

Changes:

  • Skips deferred repaints already covered by post-render sizing.
  • Routes column and summary updates through the shared helper.
  • Adds zoned and zoneless sizing and geometry tests.
File Description
projects/​igniteui-angular/​grids/​grid/​src/​grid.component.spec.ts Adds replacement and resize regression tests.
projects/​igniteui-angular/​grids/​grid/​src/​grid-base.directive.ts Tracks sizing progress and skips redundant repaints.
projects/​igniteui-angular/​grids/​core/​src/​summaries/​grid-summary.service.ts Uses the shared deferred repaint helper.
projects/​igniteui-angular/​grids/​core/​src/​common/​grid.interface.ts Declares the helper on the grid interface.

Review effort: Balanced

Comment on lines +3785 to +3790
({ key: `g${gen}c${i}`, field: `f${i}`, header: `G${gen} C${i}`, width: `${dynamicColumnWidth(gen)}px` }));

const makeDynamicData = (gen: number) => Array.from({ length: DYNAMIC_COLUMNS_ROWS }, (_, r) => {
const row: Record<string, any> = { id: r };
for (let c = 0; c < DYNAMIC_COLUMNS_COUNT; c++) {
row[`f${c}`] = `g${gen} r${r} c${c}`;
viktorkombov and others added 5 commits October 19, 2026 22:39
The hierarchical grid publishes new columns in a Promise and re-sizes
only when their count changes. When a sizing pass ran before the
publication, the deferred summary repaint was dropped, so the old headers
and widths stayed until the next change detection. Request a repaint
after a same-count replacement as well.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
In the data switch of #17792 the new data meets the old filters, so the
vertical scrollbar hides and shows again, and that repaint request
outlives the one the removed columns cancel. Filter an old column in the
new-fields case, so it fails without the fix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…1.2.x

# Conflicts:
#	projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.spec.ts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants