From 50d8fd91d5ffc68f23adc51d98de71e3e8ccb050 Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Fri, 30 Jan 2026 18:29:52 +0200 Subject: [PATCH 1/6] test(grid): Add a test --- .../grids/grid/src/grid.component.spec.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts index dcdb16a7f1a..decc6e1a448 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts @@ -95,6 +95,25 @@ describe('IgxGrid Component Tests #grid', () => { expect(fix.componentInstance.columnEventCount).toEqual(4); }); + it('should initialize a grid with data and columns if autoGenerate is set after the data', () => { + const fix = TestBed.createComponent(IgxGridTestComponent); + fix.componentInstance.data = [ + { Number: 1, String: '1', Boolean: true, Date: new Date(Date.now()) } + ]; + fix.componentInstance.columns = []; + fix.detectChanges(); + + const grid = fix.componentInstance.grid; + + expect(grid.columns.length).toBe(0); + + fix.componentInstance.autoGenerate = true; + fix.detectChanges(); + + expect(grid.columns.length).toBe(4); + expect(grid.rowList.length).toBe(1); + }); + it('should initialize a grid and change column properties during initialization', () => { const fix = TestBed.createComponent(IgxGridTestComponent); fix.componentInstance.columns = []; From 1505fbd4ddf71f5df1a10ae4615294e98a27cc5a Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Mon, 2 Feb 2026 11:24:44 +0200 Subject: [PATCH 2/6] fix(grid): trigger setup columns when autoGenerate changes --- .../grids/grid/src/grid-base.directive.ts | 16 ++++++++++++++-- .../src/row-island.component.ts | 2 +- .../grids/pivot-grid/src/pivot-grid.component.ts | 2 +- 3 files changed, 16 insertions(+), 4 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 8c8eb802ce1..656ddc2c974 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -30,7 +30,9 @@ import { ViewContainerRef, DOCUMENT, inject, - InjectionToken + InjectionToken, + SimpleChanges, + OnChanges } from '@angular/core'; import { areEqualArrays, @@ -138,7 +140,7 @@ const MINIMUM_COLUMN_WIDTH = 136; wcSkipComponentSuffix */ @Directive() export abstract class IgxGridBaseDirective implements GridType, - OnInit, DoCheck, OnDestroy, AfterContentInit, AfterViewInit { + OnInit, DoCheck, OnDestroy, AfterContentInit, AfterViewInit, OnChanges { /* blazorSuppress */ public readonly validation = inject(IgxGridValidationService); @@ -196,6 +198,7 @@ export abstract class IgxGridBaseDirective implements GridType, * * ``` */ + @WatchChanges() @Input({ transform: booleanAttribute }) public autoGenerate = false; @@ -4269,6 +4272,15 @@ export abstract class IgxGridBaseDirective implements GridType, } } + /** + * @hidden @internal + */ + public ngOnChanges(changes: SimpleChanges) { + if (changes.autoGenerate?.currentValue && this.data.length > 0 && this.columnList.length === 0) { + this.setupColumns() + } + } + /** * @hidden * @internal diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/row-island.component.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/row-island.component.ts index 5fcbc19aa06..7376a3049fa 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/row-island.component.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/row-island.component.ts @@ -468,7 +468,7 @@ export class IgxRowIslandComponent extends IgxHierarchicalGridBaseDirective /** * @hidden */ - public ngOnChanges(changes) { + public override ngOnChanges(changes) { this.layoutChange.emit(changes); if (!this.isInit) { this.initialChanges.push(changes); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts index 5a3d920d719..f8c15501068 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts @@ -1020,7 +1020,7 @@ export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnIni /** * @hidden @internal */ - public ngOnChanges(changes: SimpleChanges) { + public override ngOnChanges(changes: SimpleChanges) { if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) { this._shouldUpdateSizes = true; resizeObservable(this.verticalScrollContainer.displayContainer).pipe(take(1), takeUntil(this.destroy$)).subscribe(() => this.resizeNotify.next()); From 4d924dd965cbea57cec52fa94d4277939787ce55 Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Mon, 2 Feb 2026 11:37:23 +0200 Subject: [PATCH 3/6] fix(grid): add additional check if there is data --- projects/igniteui-angular/grids/grid/src/grid-base.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 656ddc2c974..8c654ef81ec 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -4276,7 +4276,7 @@ export abstract class IgxGridBaseDirective implements GridType, * @hidden @internal */ public ngOnChanges(changes: SimpleChanges) { - if (changes.autoGenerate?.currentValue && this.data.length > 0 && this.columnList.length === 0) { + if (changes.autoGenerate?.currentValue && this.data?.length > 0 && this.columnList?.length === 0) { this.setupColumns() } } From 8e85805e35b810dfda8a63cbbf8c245f910a9824 Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Mon, 2 Feb 2026 12:12:46 +0200 Subject: [PATCH 4/6] fix(watch-changes): improve ngOnChanges check during initialization --- projects/igniteui-angular/grids/core/src/watch-changes.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/igniteui-angular/grids/core/src/watch-changes.ts b/projects/igniteui-angular/grids/core/src/watch-changes.ts index d4db75c573a..cbd4bb75f28 100644 --- a/projects/igniteui-angular/grids/core/src/watch-changes.ts +++ b/projects/igniteui-angular/grids/core/src/watch-changes.ts @@ -22,7 +22,8 @@ export function WatchChanges(): PropertyDecorator { const oldValue = this[key]; if (val !== oldValue || (typeof val === 'object' && val === oldValue)) { originalSetter.call(this, val); - if (this.ngOnChanges && !init) { + // Explicitly check whether the decorator is called during initialization + if (this.ngOnChanges && init !== undefined && !init) { // in case wacthed prop changes trigger ngOnChanges manually const changes: SimpleChanges = { [key]: new SimpleChange(oldValue, val, false) From 1d88ba035619caacf10a8a8b3462202311498fe2 Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Mon, 2 Feb 2026 15:23:41 +0200 Subject: [PATCH 5/6] fix(grid): refine ngOnChanges logic for autoGenerate --- .../grids/grid/src/grid-base.directive.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 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 8c654ef81ec..a97605a60cf 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -111,7 +111,7 @@ import { IgxGridGroupByAreaComponent } from './grouping/grid-group-by-area.compo import { IgxPaginatorToken, type IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxSnackbarComponent } from 'igniteui-angular/snackbar'; import { CharSeparatedValueData, DropPosition, FilterMode, getUUID, GridCellMergeMode, GridKeydownTargetType, GridPagingMode, GridSelectionMode, GridSelectionRange, GridServiceType, GridSummaryPosition, GridType, GridValidationTrigger, IActiveNode, IActiveNodeChangeEventArgs, ICellPosition, IClipboardOptions, IColumnMovingEndEventArgs, IColumnMovingEventArgs, IColumnMovingStartEventArgs, IColumnResizeEventArgs, IColumnsAutoGeneratedEventArgs, IColumnSelectionEventArgs, IColumnVisibilityChangedEventArgs, IColumnVisibilityChangingEventArgs, IFilteringEventArgs, IGridCellEventArgs, IGridClipboardEvent, IGridContextMenuEventArgs, IGridEditDoneEventArgs, IGridEditEventArgs, IGridFormGroupCreatedEventArgs, IGridKeydownEventArgs, IGridRowEventArgs, IGridScrollEventArgs, IGridToolbarExportEventArgs, IGridValidationStatusEventArgs, IGX_GRID_SERVICE_BASE, IgxAdvancedFilteringDialogComponent, IgxCell, IgxColumnComponent, IgxColumnGroupComponent, IgxColumnResizingService, IgxDragIndicatorIconDirective, IgxEditRow, IgxExcelStyleHeaderIconDirective, IgxExcelStyleLoadingValuesTemplateDirective, IgxFilteringService, IgxGridBodyDirective, IgxGridCellComponent, IgxGridColumnResizerComponent, IgxGridEmptyTemplateContext, IgxGridEmptyTemplateDirective, IgxGridExcelStyleFilteringComponent, IgxGridFilteringCellComponent, IgxGridFilteringRowComponent, IgxGridHeaderComponent, IgxGridHeaderGroupComponent, IgxGridHeaderRowComponent, IgxGridHeaderTemplateContext, IgxGridLoadingTemplateDirective, IgxGridNavigationService, IgxGridPinningActionsComponent, IgxGridRowDragGhostContext, IgxGridRowEditActionsTemplateContext, IgxGridRowEditTemplateContext, IgxGridRowEditTextTemplateContext, IgxGridRowTemplateContext, IgxGridSelectionService, IgxGridSummaryService, IgxGridTemplateContext, IgxGridToolbarComponent, IgxGridTransaction, IgxGridValidationService, IgxHeaderCollapsedIndicatorDirective, IgxHeaderExpandedIndicatorDirective, IgxHeadSelectorDirective, IgxHeadSelectorTemplateContext, IgxRowAddTextDirective, IgxRowCollapsedIndicatorDirective, IgxRowDirective, IgxRowDragGhostDirective, IgxRowEditActionsDirective, IgxRowEditTabStopDirective, IgxRowEditTemplateDirective, IgxRowEditTextDirective, IgxRowExpandedIndicatorDirective, IgxRowSelectorDirective, IgxRowSelectorTemplateContext, IgxSortAscendingHeaderIconDirective, IgxSortDescendingHeaderIconDirective, IgxSortHeaderIconDirective, IgxSummaryRowComponent, IgxToolbarToken, IPinColumnCancellableEventArgs, IPinColumnEventArgs, IPinningConfig, IPinRowEventArgs, IRowDataCancelableEventArgs, IRowDataEventArgs, IRowDragEndEventArgs, IRowDragStartEventArgs, IRowSelectionEventArgs, IRowToggleEventArgs, ISearchInfo, ISizeInfo, ISortingEventArgs, RowEditPositionStrategy, RowPinningPosition, RowType, WatchChanges } from 'igniteui-angular/grids/core'; -import { getCurrentI18n, getNumberFormatter, IResourceChangeEventArgs, } from 'igniteui-i18n-core'; +import { getCurrentI18n, getNumberFormatter, IResourceChangeEventArgs } from 'igniteui-i18n-core'; import { I18N_FORMATTER } from 'igniteui-angular/core'; /** @@ -4050,8 +4050,8 @@ export abstract class IgxGridBaseDirective implements GridType, const activeRow = this.navigation.activeNode?.row; const selectedCellIndexes = this.selectionService.selection - ? Array.from(this.selectionService.selection.keys()) - : []; + ? Array.from(this.selectionService.selection.keys()) + : []; this._activeRowIndexes = [activeRow, ...selectedCellIndexes]; return this._activeRowIndexes; } @@ -4276,8 +4276,9 @@ export abstract class IgxGridBaseDirective implements GridType, * @hidden @internal */ public ngOnChanges(changes: SimpleChanges) { - if (changes.autoGenerate?.currentValue && this.data?.length > 0 && this.columnList?.length === 0) { - this.setupColumns() + if (!changes.autoGenerate?.firstChange && changes.autoGenerate?.currentValue && this.data?.length > 0 && this.columnList?.length === 0) { + // Make sure to setup columns only after the grid is initialized and autoGenerate is changed + this.setupColumns(); } } @@ -6796,7 +6797,7 @@ export abstract class IgxGridBaseDirective implements GridType, } else if (this.width !== null) { this._columnWidth = Math.max(parseFloat(possibleWidth), this.minColumnWidth) + 'px' } else { - this._columnWidth = this.minColumnWidth + 'px'; + this._columnWidth = this.minColumnWidth + 'px'; } } this._updateColumnDefaultWidths(); From 3d906467233fd32fee1808b3cb7f3438e055bae7 Mon Sep 17 00:00:00 2001 From: Martin Dragnev Date: Mon, 20 Apr 2026 17:43:49 +0300 Subject: [PATCH 6/6] fix(*): move column list changes event subscription --- .../grids/grid/src/grid-base.directive.ts | 13 ++++++------- 1 file changed, 6 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 a97605a60cf..55e196509a9 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -4036,6 +4036,11 @@ export abstract class IgxGridBaseDirective implements GridType, } this.setupColumns(); + this.columnList.changes + .pipe(takeUntil(this.destroy$)) + .subscribe((change: QueryList) => { + this.onColumnsChanged(change); + }); this.toolbar.changes.pipe(filter(() => !this._init), takeUntil(this.destroy$)).subscribe(() => this.notifyChanges(true)); this.setUpPaginator(); this.paginationComponents.changes.pipe(takeUntil(this.destroy$)).subscribe(() => { @@ -4276,7 +4281,7 @@ export abstract class IgxGridBaseDirective implements GridType, * @hidden @internal */ public ngOnChanges(changes: SimpleChanges) { - if (!changes.autoGenerate?.firstChange && changes.autoGenerate?.currentValue && this.data?.length > 0 && this.columnList?.length === 0) { + if (!changes.autoGenerate?.firstChange && changes.autoGenerate?.currentValue && this.data?.length > 0 && this.columnList?.length === 0 && this.columns.length === 0) { // Make sure to setup columns only after the grid is initialized and autoGenerate is changed this.setupColumns(); } @@ -6930,12 +6935,6 @@ export abstract class IgxGridBaseDirective implements GridType, this.initColumns(this._columns, (col: IgxColumnComponent) => this.columnInit.emit(col)); this.columnListDiffer.diff(this.columnList); this._calculateRowCount(); - - this.columnList.changes - .pipe(takeUntil(this.destroy$)) - .subscribe((change: QueryList) => { - this.onColumnsChanged(change); - }); } protected getColumnList() {