From 1cf4ab90a9bbc66b210efe9db6e540298c9ed47f Mon Sep 17 00:00:00 2001 From: Viktor Kombov Date: Mon, 10 Aug 2026 18:57:40 +0300 Subject: [PATCH 1/2] fix(for-of): correct virtualized sizing for bordered lists --- .../for-of/for_of.directive.spec.ts | 23 +++++++++++++++++++ .../src/directives/for-of/for_of.directive.ts | 14 +++++++++-- .../excel-style-search.component.ts | 2 +- .../grids/grid/src/grid-filtering-ui.spec.ts | 12 ++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts index 0d8139e0c17..087a876a683 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts @@ -358,6 +358,25 @@ describe('IgxForOf directive -', () => { expect(cache).toEqual([130, 100, 100, 100, 100, 100, 100, 130, 130, 130]); }); + it('should take item borders and margins into account when calculating its size', () => { + const virtualContainer = fix.componentInstance.parentVirtDir; + const node = document.createElement('div'); + node.style.width = '100px'; + node.style.height = '80px'; + node.style.border = '2px solid transparent'; + node.style.margin = '3px 5px 7px 11px'; + fix.nativeElement.appendChild(node); + + virtualContainer.igxForScrollOrientation = 'vertical'; + const verticalSize = node.getBoundingClientRect().height + 3 + 7; + expect(virtualContainer.testGetNodeSize(node)).toBe(verticalSize); + + virtualContainer.igxForScrollOrientation = 'horizontal'; + virtualContainer.igxForSizePropName = 'width'; + const horizontalSize = node.getBoundingClientRect().width + 5 + 11; + expect(virtualContainer.testGetNodeSize(node)).toBe(horizontalSize); + }); + it('should render no more that initial chunk size elements when set if no containerSize', () => { fix.componentInstance.height = undefined; fix.componentInstance.initialChunkSize = 3; @@ -1386,6 +1405,10 @@ export class TestIgxForOfDirective extends IgxForOfDirective { public testGetHorizontalIndexAt(left, set) { super.getIndexAt(left, set); } + + public testGetNodeSize(node: Element): number { + return super.getNodeSize(node, 0); + } } /** Empty virtualized component */ diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts index 059443a4b27..da6b2498b55 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts @@ -848,8 +848,8 @@ export class IgxForOfDirective extends IgxForOfToken extends IgxForOfToken type.name || typeof type; diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-search.component.ts b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-search.component.ts index 18649187a00..0ae02d833eb 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-search.component.ts +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-search.component.ts @@ -363,7 +363,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { */ public get containerSize() { if (this.esf.listData.length) { - return this.list?.element.nativeElement.offsetHeight; + return this.list?.element.nativeElement.clientHeight; } // GE Nov 1st, 2021 #10355 Return a numeric value, so the chunk size is calculated properly. 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 fa81813f0f5..558d094416b 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 @@ -4086,6 +4086,18 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { expect(listItems.length).toBe(6, 'incorrect rendered list items count'); }); + it('Should use the list content height for the virtual container size', async () => { + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'ProductName'); + fix.detectChanges(); + await wait(100); + + const searchComponent = fix.debugElement.query(By.css('igx-excel-style-search')).componentInstance; + const listElement = searchComponent.list.element.nativeElement as HTMLElement; + + expect(listElement.offsetHeight).toBeGreaterThan(listElement.clientHeight); + expect(searchComponent.containerSize).toBe(listElement.clientHeight); + }); + it('Should allow to input commas in excel search component input field when column dataType is number.', async () => { GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); fix.detectChanges(); From 2147df41649785c117398cf7cf72042f571d9e76 Mon Sep 17 00:00:00 2001 From: Viktor Kombov Date: Tue, 11 Aug 2026 14:45:11 +0300 Subject: [PATCH 2/2] fix(for-of): address bordered sizing review feedback --- .../directives/for-of/for_of.directive.spec.ts | 17 +++++++++++++++++ .../src/directives/for-of/for_of.directive.ts | 8 ++++---- .../grids/grid/src/grid-filtering-ui.spec.ts | 1 + 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts index 087a876a683..81d87eab2fc 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts @@ -375,6 +375,19 @@ describe('IgxForOf directive -', () => { virtualContainer.igxForSizePropName = 'width'; const horizontalSize = node.getBoundingClientRect().width + 5 + 11; expect(virtualContainer.testGetNodeSize(node)).toBe(horizontalSize); + + node.remove(); + }); + + it('should preserve valid border sizes when another side cannot be parsed', () => { + const virtualContainer = fix.componentInstance.parentVirtDir; + const node = document.createElement('div'); + spyOn(window, 'getComputedStyle').and.returnValue({ + borderTopWidth: '', + borderBottomWidth: '2px' + } as CSSStyleDeclaration); + + expect(virtualContainer.testGetBorder(node, 'height')).toBe(2); }); it('should render no more that initial chunk size elements when set if no containerSize', () => { @@ -1409,6 +1422,10 @@ export class TestIgxForOfDirective extends IgxForOfDirective { public testGetNodeSize(node: Element): number { return super.getNodeSize(node, 0); } + + public testGetBorder(node: Element, dimension: string): number { + return super.getBorder(node, dimension); + } } /** Empty virtualized component */ diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts index da6b2498b55..62dfdc04fd6 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts @@ -1570,11 +1570,11 @@ export class IgxForOfDirective extends IgxForOfToken { const searchComponent = fix.debugElement.query(By.css('igx-excel-style-search')).componentInstance; const listElement = searchComponent.list.element.nativeElement as HTMLElement; + listElement.style.border = '1px solid transparent'; expect(listElement.offsetHeight).toBeGreaterThan(listElement.clientHeight); expect(searchComponent.containerSize).toBe(listElement.clientHeight);