From 69a068f5d1f2caa5c6742fde9ef96d2ee4a688eb Mon Sep 17 00:00:00 2001 From: Viktor Kombov Date: Thu, 23 Jul 2026 22:17:06 +0300 Subject: [PATCH 1/3] fix(grid): prevent NaN column width when hidden grid has all columns sized --- .../grids/grid/src/column.spec.ts | 49 ++++++++++++++++++- .../grids/grid/src/grid-base.directive.ts | 9 ++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/projects/igniteui-angular/grids/grid/src/column.spec.ts b/projects/igniteui-angular/grids/grid/src/column.spec.ts index fd73bc8c071..22c3b66d89a 100644 --- a/projects/igniteui-angular/grids/grid/src/column.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column.spec.ts @@ -51,7 +51,8 @@ describe('IgxGrid - Column properties #grid', () => { TemplatedContextInputColumnsComponent, ColumnHaederClassesComponent, ResizableColumnsComponent, - DOMAttributesAsSettersComponent + DOMAttributesAsSettersComponent, + GridInToggleableWrapperComponent ] }).compileComponents(); })); @@ -325,6 +326,29 @@ describe('IgxGrid - Column properties #grid', () => { expect(grid.columnList.get(1).width).toBe('300px'); }); + it('should not derive a NaN column width when the grid is hidden through its wrapper and all columns are sized', () => { + const fix = TestBed.createComponent(GridInToggleableWrapperComponent); + fix.detectChanges(); + + const grid = fix.componentInstance.grid; + + // Hide the grid through its wrapper (display: none) and force a size recalculation. + // With no width set, the hidden grid falls back to summing its column widths for + // calcWidth, so computedWidth equals sumExistingWidths while columnsToSize is 0. + fix.componentInstance.wrapperHidden = true; + fix.detectChanges(); + grid.reflow(); + fix.detectChanges(); + + const possibleWidth = grid.getPossibleColumnWidth(); + expect(possibleWidth).not.toContain('NaN'); + expect(Number.isFinite(parseFloat(possibleWidth))).toBe(true); + + // the minWidth column must keep a valid, finite pixel width rather than being poisoned by NaN + const minWidthColumn = grid.getColumnByName('field15'); + expect(Number.isFinite(minWidthColumn.calcPixelWidth)).toBe(true); + }); + it('should support passing templates through the markup as an input property', () => { const fixture = TestBed.createComponent(TemplatedInputColumnsComponent); fixture.detectChanges(); @@ -1943,6 +1967,29 @@ export class DOMAttributesAsSettersComponent { public data = [{ id: 1, value: 1 }]; } +@Component({ + template: ` +
+ + + + +
+ `, + changeDetection: ChangeDetectionStrategy.Eager, + imports: [IgxGridComponent, IgxColumnComponent] +}) +export class GridInToggleableWrapperComponent { + @ViewChild('grid', { read: IgxGridComponent, static: true }) + public grid: IgxGridComponent; + + public wrapperHidden = false; + public data = [ + { id: 1, field15: 'lorem' }, + { id: 2, field15: 'ipsum' } + ]; +} + describe('IgxGrid column autosizing in zoneless change detection #grid', () => { beforeEach(() => { TestBed.configureTestingModule({ diff --git a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts index 04af42f9e8d..88cb6f081bb 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -5636,6 +5636,15 @@ export abstract class IgxGridBaseDirective implements GridType, return '0px'; } + // When every visible column already has an explicit or constrained width there is + // nothing left to auto-size. Dividing the remaining space by `columnsToSize` (0) would + // produce NaN/±Infinity, which then poisons the cached column widths - most notably when + // the grid is hidden through a wrapper and falls back to summing the column widths, so + // `computedWidth` equals `sumExistingWidths`. Fall back to the default minimum width. + if (columnsToSize <= 0) { + return this.minColumnWidth + 'px'; + } + computedWidth -= this.featureColumnsWidth(); const columnWidth = !Number.isFinite(sumExistingWidths) ? From a790a10abf385f2d5cdd8c5d83a37010f7834f51 Mon Sep 17 00:00:00 2001 From: Viktor Kombov Date: Fri, 24 Jul 2026 11:34:12 +0300 Subject: [PATCH 2/3] fix(grid): prevent NaN column width when hidden grid has all columns sized --- .../grids/grid/src/grid-base.directive.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts index 88cb6f081bb..6e91865b916 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -5636,13 +5636,13 @@ export abstract class IgxGridBaseDirective implements GridType, return '0px'; } - // When every visible column already has an explicit or constrained width there is - // nothing left to auto-size. Dividing the remaining space by `columnsToSize` (0) would - // produce NaN/±Infinity, which then poisons the cached column widths - most notably when - // the grid is hidden through a wrapper and falls back to summing the column widths, so - // `computedWidth` equals `sumExistingWidths`. Fall back to the default minimum width. - if (columnsToSize <= 0) { - return this.minColumnWidth + 'px'; + // When there is nothing left to auto-size (columnsToSize === 0) and the grid is sizing to + // the sum of its column widths - which happens when it has no width of its own and is + // hidden through a wrapper - computedWidth equals sumExistingWidths, so the division below + // would be 0 / 0 = NaN and poison the cached column widths. Return the same "0px" sentinel + // used above so callers preserve the existing (valid) column widths instead. + if (columnsToSize <= 0 && this.isColumnWidthSum) { + return '0px'; } computedWidth -= this.featureColumnsWidth(); From 5a582f8b9f49be459eb71eff901eb032b8a53a5a Mon Sep 17 00:00:00 2001 From: Viktor Kombov Date: Fri, 24 Jul 2026 12:03:00 +0300 Subject: [PATCH 3/3] docs(grid): clarify hidden grid width fallback --- .../grids/grid/src/grid-base.directive.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts index 6e91865b916..556bd30d8ba 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -5636,11 +5636,12 @@ export abstract class IgxGridBaseDirective implements GridType, return '0px'; } - // When there is nothing left to auto-size (columnsToSize === 0) and the grid is sizing to - // the sum of its column widths - which happens when it has no width of its own and is - // hidden through a wrapper - computedWidth equals sumExistingWidths, so the division below - // would be 0 / 0 = NaN and poison the cached column widths. Return the same "0px" sentinel - // used above so callers preserve the existing (valid) column widths instead. + // When the grid has no measurable width, calculateGridWidth() falls back to the + // sum of its column widths and sets isColumnWidthSum. If all visible columns + // already have explicit or constrained widths, columnsToSize is 0 and + // computedWidth equals sumExistingWidths, resulting in 0 / 0 = NaN. + // Return the "0px" sentinel so _derivePossibleWidth() preserves the existing + // valid column widths. if (columnsToSize <= 0 && this.isColumnWidthSum) { return '0px'; }