From 904b83abfd3715359415aef87d64924681fec7b1 Mon Sep 17 00:00:00 2001 From: wnvko Date: Tue, 31 Mar 2026 11:41:07 +0300 Subject: [PATCH 1/9] fix(ESF): move custom dialog out of ESF markup --- ...el-style-conditional-filter.component.html | 7 --- ...xcel-style-conditional-filter.component.ts | 54 +++++++++++++------ .../excel-style-custom-dialog.component.html | 6 +-- .../excel-style-custom-dialog.component.ts | 45 +++------------- .../grids/grid/src/grid-filtering-ui.spec.ts | 3 +- .../test-utils/grid-functions.spec.ts | 2 +- 6 files changed, 50 insertions(+), 67 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.html b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.html index 89fbb46e625..630c7833a15 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.html +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.html @@ -43,11 +43,4 @@ } - - - } diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts index 5ed40340e94..cd420833ace 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts @@ -6,7 +6,7 @@ import { BaseFilteringComponent } from './base-filtering.component'; import { NgClass } from '@angular/common'; import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, ISelectionEventArgs } from 'igniteui-angular/drop-down'; import { IgxIconComponent } from 'igniteui-angular/icon'; -import { AbsoluteScrollStrategy, AutoPositionStrategy, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, OverlaySettings, PlatformUtil, VerticalAlignment } from 'igniteui-angular/core'; +import { AbsoluteScrollStrategy, AutoPositionStrategy, ContainerPositionStrategy, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, IgxOverlayService, OverlaySettings, PlatformUtil, VerticalAlignment } from 'igniteui-angular/core'; /** @@ -15,17 +15,12 @@ import { AbsoluteScrollStrategy, AutoPositionStrategy, GridColumnDataType, Horiz @Component({ selector: 'igx-excel-style-conditional-filter', templateUrl: './excel-style-conditional-filter.component.html', - imports: [NgClass, IgxDropDownItemNavigationDirective, IgxIconComponent, IgxDropDownComponent, IgxDropDownItemComponent, IgxExcelStyleCustomDialogComponent] + imports: [NgClass, IgxDropDownItemNavigationDirective, IgxIconComponent, IgxDropDownComponent, IgxDropDownItemComponent] }) export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { public esf = inject(BaseFilteringComponent); protected platform = inject(PlatformUtil); - - /** - * @hidden @internal - */ - @ViewChild('customDialog', { read: IgxExcelStyleCustomDialogComponent }) - public customDialog: IgxExcelStyleCustomDialogComponent; + private _overlayService = inject(IgxOverlayService); /** * @hidden @internal @@ -133,20 +128,47 @@ export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { * @hidden @internal */ public onSubMenuSelection(eventArgs: ISelectionEventArgs) { - if (this.esf.expressionsList && this.esf.expressionsList.length && - this.esf.expressionsList[0].expression.condition.name !== 'in') { - this.customDialog.expressionsList = this.esf.expressionsList; - } else { - this.customDialog.expressionsList = this.customDialog.expressionsList.filter(e => e.expression.fieldName === this.esf.column.field && e.expression.condition); - } + const overlaySettings: OverlaySettings = { + modal: false, + closeOnOutsideClick: true, + positionStrategy: new ContainerPositionStrategy(), + scrollStrategy: new AbsoluteScrollStrategy() + }; + const overlayId = this._overlayService.attach(IgxExcelStyleCustomDialogComponent, this.esf.grid.viewRef, overlaySettings); + const overlayInfo = this._overlayService.getOverlayById(overlayId); + const customDialog = overlayInfo.componentRef.instance as IgxExcelStyleCustomDialogComponent; + this.esf.grid.tbody.nativeElement.appendChild(overlayInfo.wrapperElement.parentElement); + + this._overlayService.opening.pipe(takeUntil(this.destroy$)).subscribe((args) => { + if (args.id === overlayId) { + customDialog.esf = this.esf; + customDialog.column = this.esf.column; + customDialog.filteringService = this.esf.grid.filteringService; + customDialog.overlayComponentId = overlayId; + customDialog.selectedOperator = eventArgs.newSelection.value; + if (this.esf.expressionsList && this.esf.expressionsList.length && + this.esf.expressionsList[0].expression.condition.name !== 'in') { + customDialog.expressionsList = this.esf.expressionsList; + } else { + customDialog.expressionsList = customDialog.expressionsList + .filter(e => e.expression.fieldName === this.esf.column.field && e.expression.condition); + } + customDialog.onCustomDialogOpening(); + } + }); + this._overlayService.opened.pipe(takeUntil(this.destroy$)).subscribe((args) => { + if (args.id === overlayId) { + customDialog.onCustomDialogOpened(); + } + }); - this.customDialog.selectedOperator = eventArgs.newSelection.value; eventArgs.cancel = true; if (this.esf.overlayComponentId) { this.esf.hide(); } this.subMenu.close(); - this.customDialog.open(this.esf.mainDropdown.nativeElement); + + this._overlayService.show(overlayId); } /** diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.html b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.html index 9998443fd1f..30c47aea6aa 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.html +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.html @@ -1,12 +1,10 @@ -
+ (keydown)="onKeyDown($event)">

{{ grid.resourceStrings.igx_grid_excel_custom_dialog_header }}{{ column.header || column.field }} diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts index 0abbe0633f2..3d8478b282f 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts @@ -1,13 +1,13 @@ -import { Component, Input, ChangeDetectorRef, ViewChild, AfterViewInit, TemplateRef, ViewChildren, QueryList, ElementRef, inject } from '@angular/core'; +import { Component, Input, ChangeDetectorRef, ViewChild, TemplateRef, ViewChildren, QueryList, ElementRef, inject } from '@angular/core'; import { IgxFilteringService } from '../grid-filtering.service'; import { ILogicOperatorChangedArgs, IgxExcelStyleDefaultExpressionComponent } from './excel-style-default-expression.component'; import { IgxExcelStyleDateExpressionComponent } from './excel-style-date-expression.component'; import { ExpressionUI } from './common'; import { NgClass } from '@angular/common'; import { BaseFilteringComponent } from './base-filtering.component'; -import { IgxButtonDirective, IgxToggleDirective } from 'igniteui-angular/directives'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; -import { AbsoluteScrollStrategy, AutoPositionStrategy, ColumnType, FilteringLogic, GridColumnDataType, HorizontalAlignment, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxOverlayService, IgxStringFilteringOperand, IgxTimeFilteringOperand, OverlaySettings, PlatformUtil, PositionSettings, VerticalAlignment } from 'igniteui-angular/core'; +import { ColumnType, FilteringLogic, GridColumnDataType, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxOverlayService, IgxStringFilteringOperand, IgxTimeFilteringOperand, PlatformUtil } from 'igniteui-angular/core'; /** * @hidden @@ -15,13 +15,13 @@ import { AbsoluteScrollStrategy, AutoPositionStrategy, ColumnType, FilteringLogi @Component({ selector: 'igx-excel-style-custom-dialog', templateUrl: './excel-style-custom-dialog.component.html', - imports: [IgxToggleDirective, NgClass, IgxExcelStyleDateExpressionComponent, IgxExcelStyleDefaultExpressionComponent, IgxButtonDirective, IgxIconComponent] + imports: [NgClass, IgxExcelStyleDateExpressionComponent, IgxExcelStyleDefaultExpressionComponent, IgxButtonDirective, IgxIconComponent] }) -export class IgxExcelStyleCustomDialogComponent implements AfterViewInit { +export class IgxExcelStyleCustomDialogComponent { protected overlayService = inject(IgxOverlayService); private cdr = inject(ChangeDetectorRef); protected platform = inject(PlatformUtil); - public esf = inject(BaseFilteringComponent); + public esf: BaseFilteringComponent; @Input() public expressionsList = new Array(); @@ -38,9 +38,6 @@ export class IgxExcelStyleCustomDialogComponent implements AfterViewInit { @Input() public overlayComponentId: string; - @ViewChild('toggle', { read: IgxToggleDirective, static: true }) - public toggle: IgxToggleDirective; - @ViewChild('defaultExpressionTemplate', { read: TemplateRef }) protected defaultExpressionTemplate: TemplateRef; @@ -56,24 +53,6 @@ export class IgxExcelStyleCustomDialogComponent implements AfterViewInit { @ViewChildren(IgxExcelStyleDateExpressionComponent) private expressionDateComponents: QueryList; - private _customDialogPositionSettings: PositionSettings = { - verticalDirection: VerticalAlignment.Middle, - horizontalDirection: HorizontalAlignment.Center, - horizontalStartPoint: HorizontalAlignment.Center, - verticalStartPoint: VerticalAlignment.Middle - }; - - private _customDialogOverlaySettings: OverlaySettings = { - closeOnOutsideClick: true, - modal: false, - positionStrategy: new AutoPositionStrategy(this._customDialogPositionSettings), - scrollStrategy: new AbsoluteScrollStrategy() - }; - - public ngAfterViewInit(): void { - this._customDialogOverlaySettings.outlet = this.grid.outlet; - } - public get template(): TemplateRef { if (this.column.dataType === GridColumnDataType.Date) { return this.dateExpressionTemplate; @@ -98,15 +77,6 @@ export class IgxExcelStyleCustomDialogComponent implements AfterViewInit { } } - public open(esf) { - this._customDialogOverlaySettings.target = - this.overlayComponentId ? - this.grid.rootGrid ? this.grid.rootGrid.nativeElement : this.grid.nativeElement : - esf; - this.toggle.open(this._customDialogOverlaySettings); - this.overlayComponentId = this.toggle.overlayId; - } - public onClearButtonClick() { this.filteringService.clearFilter(this.column.field); this.selectedOperator = null; @@ -117,9 +87,8 @@ export class IgxExcelStyleCustomDialogComponent implements AfterViewInit { public closeDialog() { if (this.overlayComponentId) { this.overlayService.hide(this.overlayComponentId); + this.overlayService.detach(this.overlayComponentId); this.overlayComponentId = null; - } else { - this.toggle.close(); } } diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts index e835d0aa12b..582cc10541b 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts @@ -4203,6 +4203,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); // Open excel style custom filtering dialog and verify its size + setElementSize(grid.nativeElement, ɵSize.Large); GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); GridFunctions.clickExcelFilterCascadeButton(fix); @@ -7563,7 +7564,7 @@ const verifyExcelCustomFilterSize = (fix: ComponentFixture, expectedSize: const verifyGridSubmenuSize = (gridNativeElement: HTMLElement, expectedSize: ɵSize) => { const outlet = gridNativeElement.querySelector('.igx-grid__outlet'); const dropdowns = Array.from(outlet.querySelectorAll('.igx-drop-down__list')); - const visibleDropdown: any = dropdowns.find((d) => !d.classList.contains('igx-toggle--hidden')); + const visibleDropdown: any = dropdowns[0]; const dropdownItems = visibleDropdown.querySelectorAll('igx-drop-down-item'); dropdownItems.forEach((dropdownItem) => { diff --git a/projects/igniteui-angular/test-utils/grid-functions.spec.ts b/projects/igniteui-angular/test-utils/grid-functions.spec.ts index bf0b8125a4d..de38c8d9171 100644 --- a/projects/igniteui-angular/test-utils/grid-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-functions.spec.ts @@ -1404,7 +1404,7 @@ export class GridFunctions { input.click(); fix.detectChanges(); - const operators = fix.nativeElement.querySelectorAll('.igx-drop-down__list-scroll')[expressionIndex + 1]; + const operators = fix.nativeElement.querySelectorAll('.igx-drop-down__list-scroll')[expressionIndex]; const operator = operators.children[itemIndex].children[0]; operator.click(); tick(); From ec2a77e7ae0dedd508f3c8f3b387e15e21454281 Mon Sep 17 00:00:00 2001 From: wnvko Date: Tue, 31 Mar 2026 11:49:04 +0300 Subject: [PATCH 2/9] chore(esf): fix imports order --- .../excel-style-custom-dialog.component.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts index 3d8478b282f..043b55ffd3a 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts @@ -1,13 +1,13 @@ -import { Component, Input, ChangeDetectorRef, ViewChild, TemplateRef, ViewChildren, QueryList, ElementRef, inject } from '@angular/core'; -import { IgxFilteringService } from '../grid-filtering.service'; -import { ILogicOperatorChangedArgs, IgxExcelStyleDefaultExpressionComponent } from './excel-style-default-expression.component'; -import { IgxExcelStyleDateExpressionComponent } from './excel-style-date-expression.component'; -import { ExpressionUI } from './common'; import { NgClass } from '@angular/common'; -import { BaseFilteringComponent } from './base-filtering.component'; +import { ChangeDetectorRef, Component, ElementRef, Input, QueryList, TemplateRef, ViewChild, ViewChildren, inject } from '@angular/core'; +import { ColumnType, FilteringLogic, GridColumnDataType, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxOverlayService, IgxStringFilteringOperand, IgxTimeFilteringOperand, PlatformUtil } from 'igniteui-angular/core'; import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; -import { ColumnType, FilteringLogic, GridColumnDataType, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxOverlayService, IgxStringFilteringOperand, IgxTimeFilteringOperand, PlatformUtil } from 'igniteui-angular/core'; +import { IgxFilteringService } from '../grid-filtering.service'; +import { BaseFilteringComponent } from './base-filtering.component'; +import { ExpressionUI } from './common'; +import { IgxExcelStyleDateExpressionComponent } from './excel-style-date-expression.component'; +import { ILogicOperatorChangedArgs, IgxExcelStyleDefaultExpressionComponent } from './excel-style-default-expression.component'; /** * @hidden From 0d54fd21a674dee5a4d28df0763073f202937d09 Mon Sep 17 00:00:00 2001 From: wnvko Date: Tue, 31 Mar 2026 14:49:41 +0300 Subject: [PATCH 3/9] chore(esf): address PR comments --- ...xcel-style-conditional-filter.component.ts | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts index cd420833ace..67a7d2a5dd4 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts @@ -131,35 +131,32 @@ export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { const overlaySettings: OverlaySettings = { modal: false, closeOnOutsideClick: true, - positionStrategy: new ContainerPositionStrategy(), - scrollStrategy: new AbsoluteScrollStrategy() + positionStrategy: new ContainerPositionStrategy() }; const overlayId = this._overlayService.attach(IgxExcelStyleCustomDialogComponent, this.esf.grid.viewRef, overlaySettings); const overlayInfo = this._overlayService.getOverlayById(overlayId); const customDialog = overlayInfo.componentRef.instance as IgxExcelStyleCustomDialogComponent; this.esf.grid.tbody.nativeElement.appendChild(overlayInfo.wrapperElement.parentElement); + customDialog.esf = this.esf; + customDialog.column = this.esf.column; + customDialog.filteringService = this.esf.grid.filteringService; + customDialog.overlayComponentId = overlayId; + if (this.esf.expressionsList && this.esf.expressionsList.length && + this.esf.expressionsList[0].expression.condition.name !== 'in') { + customDialog.expressionsList = this.esf.expressionsList; + } else { + customDialog.expressionsList = customDialog.expressionsList.filter(e => e.expression.fieldName === this.esf.column.field && e.expression.condition); + } + customDialog.selectedOperator = eventArgs.newSelection.value; + this._overlayService.opening.pipe(takeUntil(this.destroy$)).subscribe((args) => { - if (args.id === overlayId) { - customDialog.esf = this.esf; - customDialog.column = this.esf.column; - customDialog.filteringService = this.esf.grid.filteringService; - customDialog.overlayComponentId = overlayId; - customDialog.selectedOperator = eventArgs.newSelection.value; - if (this.esf.expressionsList && this.esf.expressionsList.length && - this.esf.expressionsList[0].expression.condition.name !== 'in') { - customDialog.expressionsList = this.esf.expressionsList; - } else { - customDialog.expressionsList = customDialog.expressionsList - .filter(e => e.expression.fieldName === this.esf.column.field && e.expression.condition); - } + if (args.id === overlayId) customDialog.onCustomDialogOpening(); - } }); this._overlayService.opened.pipe(takeUntil(this.destroy$)).subscribe((args) => { - if (args.id === overlayId) { + if (args.id === overlayId) customDialog.onCustomDialogOpened(); - } }); eventArgs.cancel = true; @@ -167,7 +164,6 @@ export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { this.esf.hide(); } this.subMenu.close(); - this._overlayService.show(overlayId); } From 173533b55156576a2fe2f561e877b769a45e5739 Mon Sep 17 00:00:00 2001 From: wnvko Date: Wed, 1 Apr 2026 17:21:50 +0300 Subject: [PATCH 4/9] fix(esf): focus value input only when needed --- .../excel-style/excel-style-default-expression.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.ts index 209e9708d33..2f9491f00df 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.ts @@ -135,7 +135,9 @@ export class IgxExcelStyleDefaultExpressionComponent implements AfterViewInit { this.expressionUI.expression.condition = this.getCondition(value); this.expressionUI.expression.conditionName = value; - this.focus(); + if (!this.expressionUI.expression.condition.isUnary) { + this.focus(); + } } public getCondition(value: string): IFilteringOperation { From e00a74161b52824c4fa54c2ae16ae05736962fcd Mon Sep 17 00:00:00 2001 From: wnvko Date: Thu, 2 Apr 2026 10:38:44 +0300 Subject: [PATCH 5/9] fix(esf): move overlay subscriptions into ESF custom dialog component --- ...xcel-style-conditional-filter.component.ts | 9 --------- .../excel-style-custom-dialog.component.ts | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts index 67a7d2a5dd4..20c4cb76c17 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts @@ -150,15 +150,6 @@ export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { } customDialog.selectedOperator = eventArgs.newSelection.value; - this._overlayService.opening.pipe(takeUntil(this.destroy$)).subscribe((args) => { - if (args.id === overlayId) - customDialog.onCustomDialogOpening(); - }); - this._overlayService.opened.pipe(takeUntil(this.destroy$)).subscribe((args) => { - if (args.id === overlayId) - customDialog.onCustomDialogOpened(); - }); - eventArgs.cancel = true; if (this.esf.overlayComponentId) { this.esf.hide(); diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts index 043b55ffd3a..441b16fe7f6 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts @@ -1,5 +1,6 @@ import { NgClass } from '@angular/common'; import { ChangeDetectorRef, Component, ElementRef, Input, QueryList, TemplateRef, ViewChild, ViewChildren, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ColumnType, FilteringLogic, GridColumnDataType, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxOverlayService, IgxStringFilteringOperand, IgxTimeFilteringOperand, PlatformUtil } from 'igniteui-angular/core'; import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; @@ -21,7 +22,23 @@ export class IgxExcelStyleCustomDialogComponent { protected overlayService = inject(IgxOverlayService); private cdr = inject(ChangeDetectorRef); protected platform = inject(PlatformUtil); - public esf: BaseFilteringComponent; + public esf?: BaseFilteringComponent; + + constructor() { + this.overlayService.opening.pipe(takeUntilDestroyed()).subscribe((args) => { + if (args.id === this.overlayComponentId) + this.onCustomDialogOpening(); + }); + this.overlayService.opened.pipe(takeUntilDestroyed()).subscribe((args) => { + if (args.id === this.overlayComponentId) + this.onCustomDialogOpened(); + }); + + this.overlayService.closed.pipe(takeUntilDestroyed()).subscribe((args) => { + if (args.id === this.overlayComponentId) + this.closeDialog(); + }); + } @Input() public expressionsList = new Array(); From bcf82444009342b163dc2a9dfdca02a10f2c774a Mon Sep 17 00:00:00 2001 From: wnvko Date: Thu, 2 Apr 2026 10:40:51 +0300 Subject: [PATCH 6/9] fix(esf): add ViewContainerRef in grids body --- .../igniteui-angular/grids/grid/src/grid-base.directive.ts | 4 ++++ projects/igniteui-angular/grids/grid/src/grid.component.html | 1 + .../hierarchical-grid/src/hierarchical-grid.component.html | 1 + .../grids/pivot-grid/src/pivot-grid.component.html | 1 + .../grids/tree-grid/src/tree-grid.component.html | 1 + 5 files changed, 8 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 d37959ef576..e84440cc565 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -1328,6 +1328,10 @@ export abstract class IgxGridBaseDirective implements GridType, @ViewChild('tbody', { static: true }) public tbody: ElementRef; + /** @hidden @internal */ + @ViewChild("bodyViewContainerRef", { read: ViewContainerRef }) + public bodyViewContainerRef?: ViewContainerRef; + @ViewChild(IgxGridBodyDirective, { static: true, read: ElementRef }) protected tbodyContainer: ElementRef; diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.html b/projects/igniteui-angular/grids/grid/src/grid.component.html index fc70bcd36e6..b8f5df39515 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.html +++ b/projects/igniteui-angular/grids/grid/src/grid.component.html @@ -158,6 +158,7 @@
+
diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html index 474b908931c..de9b91119dd 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html @@ -125,6 +125,7 @@ id="right" class="igx-grid__scroll-on-drag-right"> }
+ @if (!this.parent) { } diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html index 5146ff7f016..4454985176e 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html @@ -60,6 +60,7 @@ +
diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.html b/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.html index dc35157c946..24efd0482df 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.html +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.html @@ -117,6 +117,7 @@
+
From 2f5875019ef7ea477a0e436acfda8af1b9dcfafd Mon Sep 17 00:00:00 2001 From: wnvko Date: Thu, 2 Apr 2026 10:58:16 +0300 Subject: [PATCH 7/9] fix(esf): use AutoPositionStrategy for ESF dialog and attach to gridBodyVCR --- ...xcel-style-conditional-filter.component.ts | 19 +++++++++++++------ .../excel-style-custom-dialog.component.ts | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts index 20c4cb76c17..bb083e85c48 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-conditional-filter.component.ts @@ -6,7 +6,7 @@ import { BaseFilteringComponent } from './base-filtering.component'; import { NgClass } from '@angular/common'; import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, ISelectionEventArgs } from 'igniteui-angular/drop-down'; import { IgxIconComponent } from 'igniteui-angular/icon'; -import { AbsoluteScrollStrategy, AutoPositionStrategy, ContainerPositionStrategy, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, IgxOverlayService, OverlaySettings, PlatformUtil, VerticalAlignment } from 'igniteui-angular/core'; +import { AbsoluteScrollStrategy, AutoPositionStrategy, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, IgxOverlayService, OverlaySettings, PlatformUtil, PositionSettings, VerticalAlignment } from 'igniteui-angular/core'; /** @@ -128,22 +128,29 @@ export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { * @hidden @internal */ public onSubMenuSelection(eventArgs: ISelectionEventArgs) { + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Center, + verticalDirection: VerticalAlignment.Middle, + horizontalStartPoint: HorizontalAlignment.Center, + verticalStartPoint: VerticalAlignment.Middle + }; const overlaySettings: OverlaySettings = { + target: this.esf.grid.tbody.nativeElement, modal: false, closeOnOutsideClick: true, - positionStrategy: new ContainerPositionStrategy() + positionStrategy: new AutoPositionStrategy(positionSettings), + scrollStrategy: new AbsoluteScrollStrategy(), }; - const overlayId = this._overlayService.attach(IgxExcelStyleCustomDialogComponent, this.esf.grid.viewRef, overlaySettings); + const overlayId = this._overlayService.attach(IgxExcelStyleCustomDialogComponent, this.esf.grid.bodyViewContainerRef, overlaySettings); const overlayInfo = this._overlayService.getOverlayById(overlayId); - const customDialog = overlayInfo.componentRef.instance as IgxExcelStyleCustomDialogComponent; - this.esf.grid.tbody.nativeElement.appendChild(overlayInfo.wrapperElement.parentElement); + const customDialog = overlayInfo.componentRef!.instance as IgxExcelStyleCustomDialogComponent; customDialog.esf = this.esf; customDialog.column = this.esf.column; customDialog.filteringService = this.esf.grid.filteringService; customDialog.overlayComponentId = overlayId; if (this.esf.expressionsList && this.esf.expressionsList.length && - this.esf.expressionsList[0].expression.condition.name !== 'in') { + this.esf.expressionsList[0].expression.condition?.name !== 'in') { customDialog.expressionsList = this.esf.expressionsList; } else { customDialog.expressionsList = customDialog.expressionsList.filter(e => e.expression.fieldName === this.esf.column.field && e.expression.condition); diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts index 441b16fe7f6..09c1ed8a43c 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts @@ -110,7 +110,7 @@ export class IgxExcelStyleCustomDialogComponent { } public cancelDialog() { - this.esf.cancel(); + this.esf?.cancel(); this.closeDialog(); } From 32aaa0f2871b864d6207e0a30af12c7905cf8889 Mon Sep 17 00:00:00 2001 From: Milko Venkov Date: Thu, 2 Apr 2026 11:22:26 +0300 Subject: [PATCH 8/9] Update projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../excel-style/excel-style-custom-dialog.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts index 09c1ed8a43c..e1837de0c1f 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-custom-dialog.component.ts @@ -35,8 +35,10 @@ export class IgxExcelStyleCustomDialogComponent { }); this.overlayService.closed.pipe(takeUntilDestroyed()).subscribe((args) => { - if (args.id === this.overlayComponentId) - this.closeDialog(); + if (args.id === this.overlayComponentId) { + this.overlayService.detach(this.overlayComponentId); + this.overlayComponentId = null; + } }); } From 3d144d4d5142e116dbaaa5d1925c947e192ec637 Mon Sep 17 00:00:00 2001 From: Damyan Petev Date: Thu, 2 Apr 2026 19:41:33 +0300 Subject: [PATCH 9/9] Update projects/igniteui-angular/grids/grid/src/grid-base.directive.ts --- 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 e84440cc565..0a20b0bba92 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -1329,7 +1329,7 @@ export abstract class IgxGridBaseDirective implements GridType, public tbody: ElementRef; /** @hidden @internal */ - @ViewChild("bodyViewContainerRef", { read: ViewContainerRef }) + @ViewChild("bodyViewContainerRef", { read: ViewContainerRef, static: true }) public bodyViewContainerRef?: ViewContainerRef; @ViewChild(IgxGridBodyDirective, { static: true, read: ElementRef })