From 904b83abfd3715359415aef87d64924681fec7b1 Mon Sep 17 00:00:00 2001 From: wnvko Date: Tue, 31 Mar 2026 11:41:07 +0300 Subject: [PATCH 1/3] 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/3] 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/3] 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); }