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 bf93ef38ea7..a9a469d5021 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 @@ -190,6 +190,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { private _containerSize = 0; private _addToCurrentFilterItem: FilterListItem; private _selectAllItem: FilterListItem; + private _measuredItemSize: number; private _hierarchicalSelectedItems: FilterListItem[]; private _focusedItem: ActiveElement = null; private destroy$ = new Subject(); @@ -261,6 +262,12 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { public refreshSize = () => { if (this.virtDir) { this.updateContainerSize(); + const firstItem = this.list?.children.first; + const itemSize = firstItem?.element.getBoundingClientRect().height; + if (itemSize) { + // Excel filter rows are uniform; use the outer size to keep the scrollbar range stable. + this._measuredItemSize = itemSize; + } this.virtDir.igxForContainerSize = this.containerSize; this.virtDir.igxForItemSize = this.itemSize; this.virtDir.recalcUpdateSizes(); @@ -351,6 +358,9 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { */ public get itemSize() { let itemSize = '40px'; + if (this._measuredItemSize) { + return `${this._measuredItemSize}px`; + } const esf = this.esf as any; switch (esf.size) { case ɵSize.Medium: itemSize = '32px'; break; diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_fluent.scss b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_fluent.scss new file mode 100644 index 00000000000..143f0a8a988 --- /dev/null +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_fluent.scss @@ -0,0 +1,9 @@ +@use 'igniteui-theming/sass/bem' as *; +@use '../../../../../../../core/src/core/styles/themes/scoping' as *; + +@include themed-block(igx-excel-filter, fluent) { + // Keep the rendered list item height stable while virtual items are recycled. + .igx-list__item-base:last-of-type { + border-bottom: var(--border-width) solid transparent; + } +} diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_index.scss b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_index.scss index dc0bbc2b1d9..0ca60c75786 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_index.scss +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_index.scss @@ -1,3 +1,4 @@ @forward 'material'; @forward 'bootstrap'; +@forward 'fluent'; @forward 'indigo'; diff --git a/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_indigo.scss b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_indigo.scss index 40abc603650..dd58370752e 100644 --- a/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_indigo.scss +++ b/projects/igniteui-angular/grids/core/src/filtering/excel-style/themes/shared/_indigo.scss @@ -119,17 +119,13 @@ $_theme: digest-schema($indigo-excel-filtering); border-block: rem(1px) dashed var(--_border-color, var(--ig-gray-100)); margin-inline: calc(#{sizable(rem(-16px))} * -1); - // This is the only way to take the gap from the list, - // otherwise we have to hardcode it here - > div { - gap: inherit; + igx-display-container { + padding-inline: pad(rem(8px)); } - igx-display-container { - display: flex; - flex-direction: column; - gap: inherit; - padding: pad(rem(8px)); + // Keep the visual spacing inside the item size measured by the virtualizer. + .igx-list__item-base { + padding-block-end: rem(4px); } } } 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 29c9b821419..b6eac714201 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 @@ -4098,13 +4098,31 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(100); const searchComponent = fix.debugElement.query(By.css('igx-excel-style-search')).componentInstance; - const listElement = searchComponent.list.element.nativeElement as HTMLElement; + const listElement = searchComponent.list.element.nativeElement; listElement.style.border = '1px solid transparent'; expect(listElement.offsetHeight).toBeGreaterThan(listElement.clientHeight); expect(searchComponent.containerSize).toBe(listElement.clientHeight); }); + it('Should initialize virtual item sizes from the rendered list item', async () => { + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'ProductName'); + fix.detectChanges(); + await wait(100); + + const searchComponent = fix.debugElement.query(By.css('igx-excel-style-search')).componentInstance; + const virtDir = searchComponent.virtDir; + const firstItem = searchComponent.list.children.first.element; + spyOn(firstItem, 'getBoundingClientRect').and.returnValue(DOMRect.fromRect({ height: 37 })); + + searchComponent.refreshSize(); + fix.detectChanges(); + + expect(searchComponent.itemSize).toBe('37px'); + expect(virtDir.igxForItemSize).toBe('37px'); + expect(virtDir.individualSizeCache.at(-1)).toBe(37); + }); + 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(); diff --git a/src/app/virtual-for-directive/virtual-for.sample.css b/src/app/virtual-for-directive/virtual-for.sample.css index 180fc1a720e..6482ee2a4d1 100644 --- a/src/app/virtual-for-directive/virtual-for.sample.css +++ b/src/app/virtual-for-directive/virtual-for.sample.css @@ -38,6 +38,10 @@ align-items: center; } +.fixed-size-item > .igx-list__item-content { + height: 100%; +} + .vertical-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); diff --git a/src/app/virtual-for-directive/virtual-for.sample.html b/src/app/virtual-for-directive/virtual-for.sample.html index c6b05e44e0d..a758900cada 100644 --- a/src/app/virtual-for-directive/virtual-for.sample.html +++ b/src/app/virtual-for-directive/virtual-for.sample.html @@ -7,8 +7,8 @@

Vertical Virtualization

- -
{{rowIndex}}: {{item.text}}
+ +
{{rowIndex}}: {{item.text}}
@@ -77,9 +77,10 @@

Variable heights

- -
{{rowIndex}}: {{item.text}}
+ +
{{rowIndex}}: {{item.text}}
@@ -94,8 +95,8 @@

Even Variable

- -
{{rowIndex}} : {{item.text}}
+ +
{{rowIndex}} : {{item.text}}