From 36764005bc4de62a39a24b965e0ca8983e1dbc9d Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 22 Apr 2026 14:16:30 +0300 Subject: [PATCH 1/8] fix(igxGrid): Hide overlays on scroll + special handling for row edit overlay. --- .../grids/grid/src/grid-base.directive.ts | 39 ++++++++++--------- .../hierarchical-grid.sample.html | 14 ++++--- .../hierarchical-grid.sample.ts | 3 +- 3 files changed, 31 insertions(+), 25 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..d33d48f1049 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -3717,10 +3717,10 @@ export abstract class IgxGridBaseDirective implements GridType, filter(() => !this._init), throttle(() => this.throttleTime$.pipe( - take(1), - switchMap(time => timer(time, this.throttleScheduler)) + take(1), + switchMap(time => timer(time, this.throttleScheduler)) ) - ), + ), destructor ) .subscribe((event) => { @@ -3747,6 +3747,15 @@ export abstract class IgxGridBaseDirective implements GridType, } } this.notifyChanges(true); + if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay.collapsed) { + // connected to DOM, row is in edit mode, but overlay is closed - reopen. + this.openRowOverlay(this.crudService.rowInEditMode.id); + } + } + + if (!this.nativeElement.isConnected && this.rowEditable && this.crudService.rowInEditMode) { + // disconnected from DOM (possibly cached) & row was in edit mode - close overlay. + this.closeRowEditingOverlay(); } }); }); @@ -3766,22 +3775,14 @@ export abstract class IgxGridBaseDirective implements GridType, this.overlayService.opened.pipe(destructor).subscribe((event) => { const overlaySettings = this.overlayService.getOverlayById(event.id)?.settings; - // do not hide the advanced filtering overlay on scroll - if (this._advancedFilteringOverlayId === event.id) { - const instance = event.componentRef.instance as IgxAdvancedFilteringDialogComponent; - if (instance) { - instance.lastActiveNode = this.navigation.activeNode; - instance.queryBuilder.setAddButtonFocus(); - } + const inRow = (overlaySettings?.target as HTMLElement)?.classList.contains("igx-grid__tr"); + // do not hide the overlay if it's attached to a row on scroll + if (inRow) { return; } - - // do not hide the overlay if it's attached to a row - if (this.rowEditingOverlay?.overlayId === event.id) { - return; - } - - if (overlaySettings?.outlet === this.outlet && this.overlayIDs.indexOf(event.id) === -1) { + // check whole grid, since some overlays like the advanced filtering, are outside the body. + const isInGrid = this.nativeElement.contains(overlaySettings?.target as Node); + if (isInGrid && this.overlayIDs.indexOf(event.id) === -1) { this.overlayIDs.push(event.id); } }); @@ -4047,8 +4048,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; } diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.html b/src/app/hierarchical-grid/hierarchical-grid.sample.html index 81ee690a48f..fed0fab9a45 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.html +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.html @@ -8,7 +8,7 @@

Sample One

@@ -53,7 +53,7 @@

Sample One

- @@ -66,10 +66,14 @@

Sample One

- + + + + {{ toolbarTitle }} + @@ -79,8 +83,8 @@

Sample One

- - + +
diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.ts b/src/app/hierarchical-grid/hierarchical-grid.sample.ts index af746d3344c..96394bbd56b 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.ts +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.ts @@ -2,6 +2,7 @@ import { Component, ViewChild, ChangeDetectorRef, AfterViewInit, HostBinding } f import { GridSearchBoxComponent } from '../grid-search-box/grid-search-box.component'; import { IgxRowIslandComponent, + IgxActionStripComponent, IgxHierarchicalGridComponent, IGridCellEventArgs, GridSelectionMode, @@ -16,7 +17,7 @@ import { selector: 'app-hierarchical-grid-sample', styleUrls: ['hierarchical-grid.sample.scss'], templateUrl: 'hierarchical-grid.sample.html', - imports: [GridSearchBoxComponent, IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxIconComponent, IGX_BUTTON_GROUP_DIRECTIVES] + imports: [GridSearchBoxComponent, IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxIconComponent, IGX_BUTTON_GROUP_DIRECTIVES, IgxActionStripComponent] }) export class HierarchicalGridSampleComponent implements AfterViewInit { @HostBinding('style.--ig-size') From 449a15c8d6cf8bcc9b8544b9bda59b3a7b79b4e9 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 22 Apr 2026 14:46:33 +0300 Subject: [PATCH 2/8] chore(*): Add back some focus handling for adv.filter. --- .../grids/grid/src/grid-base.directive.ts | 9 +++++++++ 1 file changed, 9 insertions(+) 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 d33d48f1049..c2992a49404 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -3775,6 +3775,15 @@ export abstract class IgxGridBaseDirective implements GridType, this.overlayService.opened.pipe(destructor).subscribe((event) => { const overlaySettings = this.overlayService.getOverlayById(event.id)?.settings; + // this sets focus to query builder button for some reason... + if (this._advancedFilteringOverlayId === event.id) { + const instance = event.componentRef.instance as IgxAdvancedFilteringDialogComponent; + if (instance) { + instance.lastActiveNode = this.navigation.activeNode; + instance.queryBuilder.setAddButtonFocus(); + } + } + const inRow = (overlaySettings?.target as HTMLElement)?.classList.contains("igx-grid__tr"); // do not hide the overlay if it's attached to a row on scroll if (inRow) { From 09d1cd92c7ffaf0ba6f93002ad144f2a3be7d850 Mon Sep 17 00:00:00 2001 From: Maya Date: Wed, 22 Apr 2026 14:52:21 +0300 Subject: [PATCH 3/8] chore(*): Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../igniteui-angular/grids/grid/src/grid-base.directive.ts | 5 +++-- src/app/hierarchical-grid/hierarchical-grid.sample.html | 4 ++-- 2 files changed, 5 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 c2992a49404..623bab117db 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -3747,13 +3747,14 @@ export abstract class IgxGridBaseDirective implements GridType, } } this.notifyChanges(true); - if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay.collapsed) { + if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay && + this.rowEditingOverlay.collapsed) { // connected to DOM, row is in edit mode, but overlay is closed - reopen. this.openRowOverlay(this.crudService.rowInEditMode.id); } } - if (!this.nativeElement.isConnected && this.rowEditable && this.crudService.rowInEditMode) { + if (!this.nativeElement.isConnected && this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay) { // disconnected from DOM (possibly cached) & row was in edit mode - close overlay. this.closeRowEditingOverlay(); } diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.html b/src/app/hierarchical-grid/hierarchical-grid.sample.html index fed0fab9a45..95a8c73db8a 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.html +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.html @@ -54,8 +54,8 @@

Sample One

+ [autoGenerate]="false" [allowFiltering]="true" [rowSelection]="selectionMode" + [expandChildren]="firstLevelExpanded" #layout1 filterMode="excelStyleFilter"> From 5acdcabbb417fb57ee0232d2efb5c9607183519d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 12:03:10 +0000 Subject: [PATCH 4/8] test(grid): add scroll overlay regression coverage Agent-Logs-Url: https://github.com/IgniteUI/igniteui-angular/sessions/5da777fa-12c5-4827-97a7-0bae83db17ae Co-authored-by: MayaKirova <10397980+MayaKirova@users.noreply.github.com> --- .../grid/src/grid-filtering-advanced.spec.ts | 15 +++++++++++++++ .../grids/grid/src/grid-row-editing.spec.ts | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts index 0c8c636f9b1..dfb6bcfc6d7 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts @@ -116,6 +116,21 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(GridFunctions.getAdvancedFilteringComponent(fix)).toBeNull(); })); + it('Should close Advanced Filtering dialog on vertical scroll.', fakeAsync(() => { + grid.openAdvancedFilteringDialog(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); + + (grid as any).verticalScrollHandler({ target: grid.verticalScrollContainer.getScroll() }); + tick(200); + fix.detectChanges(); + + expect(GridFunctions.getAdvancedFilteringComponent(fix)).toBeNull(); + })); + it('Should close Advanced Filtering dialog through API by respecting \'applyChanges\' argument.', fakeAsync(() => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts index ba77b0bbd7d..de48e86f82b 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts @@ -491,6 +491,22 @@ describe('IgxGrid - Row Editing #grid', () => { cell.editMode = false; }); + it('Overlay position: Should reposition row editing overlay on vertical scroll without closing it', () => { + const repositionSpy = spyOn(grid, 'repositionRowEditingOverlay').and.callThrough(); + cell = grid.getCellByColumn(0, 'ProductName'); + cell.editMode = true; + fix.detectChanges(); + + expect(grid.rowEditingOverlay.collapsed).toBeFalse(); + expect((grid as any).overlayIDs).not.toContain(grid.rowEditingOverlay.overlayId); + + (grid as any).changeRowEditingOverlayStateOnScroll(grid.crudService.rowInEditMode); + fix.detectChanges(); + + expect(repositionSpy).toHaveBeenCalled(); + expect(grid.rowEditingOverlay.collapsed).toBeFalse(); + }); + it('should end row editing when clearing or applying advanced filter', () => { fix.detectChanges(); const row = grid.gridAPI.get_row_by_index(2); From a66b6b17c8b4763fac2ca566dcf90efad1bd034b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 12:09:17 +0000 Subject: [PATCH 5/8] test(grid): refine row overlay scroll regression test Agent-Logs-Url: https://github.com/IgniteUI/igniteui-angular/sessions/5da777fa-12c5-4827-97a7-0bae83db17ae Co-authored-by: MayaKirova <10397980+MayaKirova@users.noreply.github.com> --- .../grids/grid/src/grid-row-editing.spec.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts index de48e86f82b..e14f52423bc 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts @@ -491,21 +491,20 @@ describe('IgxGrid - Row Editing #grid', () => { cell.editMode = false; }); - it('Overlay position: Should reposition row editing overlay on vertical scroll without closing it', () => { - const repositionSpy = spyOn(grid, 'repositionRowEditingOverlay').and.callThrough(); + it('Overlay position: Should keep row editing overlay open on vertical scroll', fakeAsync(() => { cell = grid.getCellByColumn(0, 'ProductName'); cell.editMode = true; fix.detectChanges(); expect(grid.rowEditingOverlay.collapsed).toBeFalse(); - expect((grid as any).overlayIDs).not.toContain(grid.rowEditingOverlay.overlayId); - (grid as any).changeRowEditingOverlayStateOnScroll(grid.crudService.rowInEditMode); + (grid as any).verticalScrollHandler({ target: grid.verticalScrollContainer.getScroll() }); + tick(); fix.detectChanges(); - expect(repositionSpy).toHaveBeenCalled(); + expect(GridFunctions.getRowEditingOverlay(fix)).toBeTruthy(); expect(grid.rowEditingOverlay.collapsed).toBeFalse(); - }); + })); it('should end row editing when clearing or applying advanced filter', () => { fix.detectChanges(); From 3000d73e965462c4db31fa1725914521f9d1eb79 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 22 Apr 2026 18:29:12 +0300 Subject: [PATCH 6/8] chore(*): Adjust logic so that adv.filtering does not close. --- .../igniteui-angular/grids/grid/src/grid-base.directive.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 c2992a49404..a1c53eaa114 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -3775,13 +3775,14 @@ export abstract class IgxGridBaseDirective implements GridType, this.overlayService.opened.pipe(destructor).subscribe((event) => { const overlaySettings = this.overlayService.getOverlayById(event.id)?.settings; - // this sets focus to query builder button for some reason... + // do not hide the advanced filtering overlay on scroll if (this._advancedFilteringOverlayId === event.id) { const instance = event.componentRef.instance as IgxAdvancedFilteringDialogComponent; if (instance) { instance.lastActiveNode = this.navigation.activeNode; instance.queryBuilder.setAddButtonFocus(); } + return; } const inRow = (overlaySettings?.target as HTMLElement)?.classList.contains("igx-grid__tr"); @@ -3789,8 +3790,8 @@ export abstract class IgxGridBaseDirective implements GridType, if (inRow) { return; } - // check whole grid, since some overlays like the advanced filtering, are outside the body. - const isInGrid = this.nativeElement.contains(overlaySettings?.target as Node); + + const isInGrid = overlaySettings?.target instanceof Node && this.tbody.nativeElement.contains(overlaySettings?.target); if (isInGrid && this.overlayIDs.indexOf(event.id) === -1) { this.overlayIDs.push(event.id); } From 3eb28689a74c3c69054f14b3907f1fdc06cd0b48 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 22 Apr 2026 18:29:44 +0300 Subject: [PATCH 7/8] chore(*): Remove copilot test. --- .../grid/src/grid-filtering-advanced.spec.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts index dfb6bcfc6d7..0c8c636f9b1 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts @@ -116,21 +116,6 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(GridFunctions.getAdvancedFilteringComponent(fix)).toBeNull(); })); - it('Should close Advanced Filtering dialog on vertical scroll.', fakeAsync(() => { - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); - - (grid as any).verticalScrollHandler({ target: grid.verticalScrollContainer.getScroll() }); - tick(200); - fix.detectChanges(); - - expect(GridFunctions.getAdvancedFilteringComponent(fix)).toBeNull(); - })); - it('Should close Advanced Filtering dialog through API by respecting \'applyChanges\' argument.', fakeAsync(() => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); From b1987b13a55c708bff60f9c7fc6a80200da17ebe Mon Sep 17 00:00:00 2001 From: MKirova Date: Thu, 23 Apr 2026 14:14:56 +0300 Subject: [PATCH 8/8] chore(*): Remove open/close logic on detach/attach. --- .../grids/grid/src/grid-base.directive.ts | 10 ---------- 1 file changed, 10 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 0161e9a0f37..64485b68d21 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -3747,16 +3747,6 @@ export abstract class IgxGridBaseDirective implements GridType, } } this.notifyChanges(true); - if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay && - this.rowEditingOverlay.collapsed) { - // connected to DOM, row is in edit mode, but overlay is closed - reopen. - this.openRowOverlay(this.crudService.rowInEditMode.id); - } - } - - if (!this.nativeElement.isConnected && this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay) { - // disconnected from DOM (possibly cached) & row was in edit mode - close overlay. - this.closeRowEditingOverlay(); } }); });