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 61fd8075565..61e9df0c223 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 @@ -501,7 +501,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { (it.label !== null && it.label !== undefined) && !it.isBlanks && (it.label.toString().toLowerCase().indexOf(searchVal) > -1 || - this.matchesNumericValue(it, searchVal))); + this.matchesNumericValue(it, searchVal))); this.esf.listData.forEach(i => i.isSelected = false); this.displayedListData.forEach(i => i.isSelected = true); @@ -610,7 +610,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { searchVal = new Set(selectedItems.map(e => e.value.toLocaleTimeString())); break; case GridColumnDataType.String: - if (this.esf.column.filteringIgnoreCase && !this.isHierarchical()) { + if (this.esf.column.filteringIgnoreCase && !this.isHierarchical() && !this.isRemoteData()) { const selectedValues = new Set(selectedItems.map(item => item.value.toLowerCase())); searchVal = new Set(); @@ -816,8 +816,8 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { const columnDataType = this.esf.column?.dataType; if (typeof item.value !== 'number' || (columnDataType !== GridColumnDataType.Number && - columnDataType !== GridColumnDataType.Currency && - columnDataType !== GridColumnDataType.Percent)) { + columnDataType !== GridColumnDataType.Currency && + columnDataType !== GridColumnDataType.Percent)) { return false; } @@ -896,4 +896,8 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { const subRequired = indexOutOfChunk || scrollNeeded; return subRequired; } + + private isRemoteData(): boolean { + return this.esf.grid.verticalScrollContainer.isRemote; + } } 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 8c5e67ef764..41f6d098626 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 @@ -24,6 +24,7 @@ import { IgxGridFilteringESFEmptyTemplatesComponent, IgxGridFilteringESFTemplatesComponent, IgxGridFilteringESFLoadOnDemandComponent, + IgxGridFilteringESFRemoteChunkComponent, CustomFilteringStrategyComponent, IgxGridExternalESFComponent, IgxGridExternalESFTemplateComponent, @@ -3223,6 +3224,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { IgxGridFilteringESFEmptyTemplatesComponent, IgxGridFilteringESFTemplatesComponent, IgxGridFilteringESFLoadOnDemandComponent, + IgxGridFilteringESFRemoteChunkComponent, IgxGridFilteringMCHComponent, IgxGridExternalESFComponent, IgxGridExternalESFTemplateComponent @@ -7068,6 +7070,40 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { tick(2000); }).not.toThrowError(/'dataType' of null/); })); + + it('Should preserve selected string values from full remote set when grid data is chunked', fakeAsync(() => { + const remoteFix = TestBed.createComponent(IgxGridFilteringESFRemoteChunkComponent); + const remoteGrid = remoteFix.componentInstance.grid; + remoteFix.detectChanges(); + + // Mark the grid as remote so ESF does not derive selected values from the current data chunk. + remoteGrid.totalItemCount = remoteFix.componentInstance.fullData.length; + + GridFunctions.clickExcelFilterIcon(remoteFix, 'ProductName'); + tick(100); + remoteFix.detectChanges(); + + const excelMenu = GridFunctions.getExcelStyleFilteringComponent(remoteFix); + const labelElements: any[] = Array.from(GridFunctions.getExcelStyleSearchComponentListItems(remoteFix, excelMenu)); + const checkboxElements: any[] = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(remoteFix, excelMenu)); + + const uncheckLabel = 'Alpha'; + const uncheckIndex = labelElements.findIndex(el => el.innerText === uncheckLabel); + expect(uncheckIndex).toBeGreaterThan(0); + + checkboxElements[uncheckIndex].click(); + remoteFix.detectChanges(); + + GridFunctions.clickApplyExcelStyleFiltering(remoteFix, excelMenu, 'igx-grid'); + remoteFix.detectChanges(); + + const tree = remoteGrid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree; + const operand = tree.filteringOperands[0] as IFilteringExpression; + + const selectedValues = Array.from((operand.searchVal as Set).values()); + expect(selectedValues).toEqual(jasmine.arrayContaining(['beta', 'Gamma', 'DELTA'])); + expect(selectedValues).not.toContain('Alpha'); + })); }); describe(null, () => { diff --git a/projects/igniteui-angular/test-utils/grid-samples.spec.ts b/projects/igniteui-angular/test-utils/grid-samples.spec.ts index 4801faf5861..e5495fddb5a 100644 --- a/projects/igniteui-angular/test-utils/grid-samples.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-samples.spec.ts @@ -874,6 +874,36 @@ export class IgxGridFilteringESFLoadOnDemandComponent extends BasicGridComponent }; } +@Component({ + template: ` + + + `, + imports: [IgxGridComponent, IgxColumnComponent] +}) +export class IgxGridFilteringESFRemoteChunkComponent extends BasicGridComponent { + public fullData = [ + { ID: 1, ProductName: 'Alpha' }, + { ID: 2, ProductName: 'beta' }, + { ID: 3, ProductName: 'Gamma' }, + { ID: 4, ProductName: 'DELTA' } + ]; + + // Simulate remote virtualization where the grid keeps only the current chunk. + public override data = this.fullData.slice(0, 2); + + private _filteringStrategy = new FilteringStrategy(); + + public columnValuesStrategy = (column: IgxColumnComponent, + columnExprTree: IFilteringExpressionsTree, + done: (uniqueValues: any[]) => void) => { + const filteredData = this._filteringStrategy.filter(this.fullData, columnExprTree, null, null); + const columnValues = filteredData.map(record => record[column.field]); + done(columnValues); + }; +} + @Component({ template: `