From ae2bbdec5e11b4f0b81ee269b7e567ba9d60d9fd Mon Sep 17 00:00:00 2001 From: "INFRAGISTICS\\IPetrov" Date: Wed, 11 Nov 2026 11:21:03 +0200 Subject: [PATCH] fix(grid): avoid double overlay detach on destroy with adv. filtering open --- CHANGELOG.md | 1 + .../grids/grid/src/grid-base.directive.ts | 6 ++- .../grid/src/grid-filtering-advanced.spec.ts | 40 ++++++++++++++++++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05a3c13bb20..fa282f51a86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ All notable changes for each version of this project will be documented in this - Autosizing a column with quick filtering enabled now fits its content and filtering chip, instead of keeping its current width or growing by 1px on each call with fractional scaling. - A single filter chip whose label is longer than the column now shrinks to the filter cell and truncates its label with an ellipsis instead of being clipped by the cell. The condition and remove icons keep their size; only a column narrower than the icons still clips the chip. The "more filters" indicator no longer shows its icon while it is hidden. - Pinned filter row cells use the pinned border, row action cells use the header border width, and selected cells and columns no longer show stray borders. + - Destroying the grid while its advanced filtering dialog is open no longer logs `igxOverlay.detach was called with wrong id` in the console. - `IgxGridComponent` - Autosizing a child column of a column layout now fits its content, instead of keeping the width of its layout area. - When grouping is applied and no column is pinned at the start, the group-by indentation and the summary area below it use the pinned border. 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 18098e8e9c9..117f6acb989 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -4445,10 +4445,12 @@ export abstract class IgxGridBaseDirective implements GridType, this.textHighlightService.destroyGroup(this.id); - if (this._advancedFilteringOverlayId) { + // The overlay service detaches the dialog on its own when Angular destroys it, which happens + // before this hook because the dialog is created in the grid's view container. + if (this._advancedFilteringOverlayId && this.overlayService.getOverlayById(this._advancedFilteringOverlayId)) { this.overlayService.detach(this._advancedFilteringOverlayId); - this._advancedFilteringOverlayId = ''; } + this._advancedFilteringOverlayId = ''; this.overlayIDs.forEach(overlayID => { const overlay = this.overlayService.getOverlayById(overlayID); 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 804ec975a48..7e4bb90ad14 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 @@ -14,7 +14,7 @@ import { FilteringExpressionsTree, FilteringLogic, FormattedValuesFilteringStrat import { QueryBuilderSelectors } from 'igniteui-angular/query-builder/src/query-builder/query-builder.common'; import { IgxDateTimeEditorDirective } from 'igniteui-angular/directives'; import { IGridCreatedEventArgs, IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular/grids/hierarchical-grid'; -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild, inject } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild, inject, signal, viewChild } from '@angular/core'; import { IgxColumnComponent } from 'igniteui-angular/grids/core'; import { describe, it, expect, beforeEach, vi } from 'vitest'; @@ -32,7 +32,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { IgxGridAdvancedFilteringWithToolbarComponent, IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridExportComponent, - IgxHGridRemoteOnDemandComponent + IgxHGridRemoteOnDemandComponent, + IgxGridAdvancedFilteringConditionalComponent ], providers: [ IgxGridNavigationService @@ -82,6 +83,26 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(document.querySelector('.igx-advanced-filter')).toBeNull(); }); + it('Should not warn about a wrong overlay id when the grid is destroyed while the dialog is opened - issue #17962', async () => { + const conditionalFix = TestBed.createComponent(IgxGridAdvancedFilteringConditionalComponent); + conditionalFix.detectChanges(); + await conditionalFix.whenStable(); + const warnSpy = vi.spyOn(console, 'warn'); + + conditionalFix.componentInstance.grid()!.openAdvancedFilteringDialog(); + conditionalFix.detectChanges(); + await conditionalFix.whenStable(); + expect(document.querySelector('.igx-advanced-filter')).not.toBeNull(); + + conditionalFix.componentInstance.showGrid.set(false); + conditionalFix.detectChanges(); + await conditionalFix.whenStable(); + + expect(conditionalFix.componentInstance.grid()).toBeUndefined(); + expect(document.querySelector('.igx-advanced-filter')).toBeNull(); + expect(warnSpy).not.toHaveBeenCalledWith('igxOverlay.detach was called with wrong id: ', expect.anything()); + }); + it('Should correctly initialize the Advanced Filtering dialog.', async () => { // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); @@ -2057,3 +2078,18 @@ class IgxHierarchicalGridMissingChildDataComponent { { root1: 3, root2: 3, level1data: [] } ]; } + +@Component({ + template: ` + @if (showGrid()) { + + + + }`, + imports: [IgxGridComponent, IgxColumnComponent] +}) +class IgxGridAdvancedFilteringConditionalComponent { + public grid = viewChild(IgxGridComponent); + public showGrid = signal(true); + public data = SampleTestData.excelFilteringData(); +}