@@ -2,12 +2,13 @@ import { FilteringLogic, type IFilteringExpression } from './filtering-expressio
22import { FilteringExpressionsTree , type IFilteringExpressionsTree } from './filtering-expressions-tree' ;
33import { resolveNestedPath , parseDate , formatDate , formatCurrency , columnFieldPath } from '../core/utils' ;
44import type { ColumnType , EntityType , GridType } from '../grids/common/grid.interface' ;
5- import { GridColumnDataType } from './data-util' ;
5+ import { DataUtil , GridColumnDataType } from './data-util' ;
66import { SortingDirection } from './sorting-strategy' ;
77import { formatNumber , formatPercent , getLocaleCurrencyCode } from '@angular/common' ;
88import type { IFilteringState } from './filtering-state.interface' ;
99import { isTree } from './expressions-tree-util' ;
1010import type { IgxHierarchicalGridComponent } from '../grids/hierarchical-grid/hierarchical-grid.component' ;
11+ import { IgxSorting } from '../grids/common/strategy' ;
1112
1213const DateType = 'date' ;
1314const DateTimeType = 'dateTime' ;
@@ -132,23 +133,27 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
132133 public getFilterItems ( column : ColumnType , tree : IFilteringExpressionsTree ) : Promise < IgxFilterItem [ ] > {
133134 const applyFormatter = column . formatter && this . shouldFormatFilterValues ( column ) ;
134135
135- let data = column . grid . gridAPI . filterDataByExpressions ( tree ) ;
136- data = column . grid . gridAPI . sortDataByExpressions ( data ,
137- [ { fieldName : column . field , dir : SortingDirection . Asc , ignoreCase : column . sortingIgnoreCase } ] ) ;
138-
136+ const data = column . grid . gridAPI . filterDataByExpressions ( tree ) ;
139137
140138 const pathParts = columnFieldPath ( column . field )
141- let filterItems : IgxFilterItem [ ] = data . map ( record => {
142- const value = applyFormatter ?
143- column . formatter ( resolveNestedPath ( record , pathParts ) , record ) :
144- resolveNestedPath ( record , pathParts ) ;
145-
146- return {
147- value,
148- label : this . getFilterItemLabel ( column , value , ! applyFormatter , record )
149- } ;
150- } ) ;
151- filterItems = this . getUniqueFilterItems ( column , filterItems ) ;
139+ const seenFormattedFilterItems = new Map < any , IgxFilterItem > ( )
140+
141+ for ( let i = 0 ; i < data . length ; ++ i ) {
142+ const record = this . getRecord ( data [ i ] ) ;
143+ const rawValue = resolveNestedPath ( record , pathParts ) ;
144+ const formattedValue = applyFormatter ? column . formatter ( rawValue , record ) : rawValue ;
145+ const { key, finalValue } = this . getFilterItemKeyValue ( formattedValue , column ) ;
146+ // Deduplicate by normalized key
147+ if ( ! seenFormattedFilterItems . has ( key ) ) {
148+ const label = this . getFilterItemLabel ( column , finalValue , ! applyFormatter , record ) ;
149+ seenFormattedFilterItems . set ( key , { value : finalValue , label } ) ;
150+ }
151+ }
152+
153+ let filterItems : IgxFilterItem [ ] = Array . from ( seenFormattedFilterItems . values ( ) ) ;
154+
155+ filterItems = DataUtil . sort ( filterItems ,
156+ [ { fieldName : 'value' , dir : SortingDirection . Asc , ignoreCase : column . sortingIgnoreCase } ] , new IgxSorting ( ) )
152157
153158 return Promise . resolve ( filterItems ) ;
154159 }
@@ -180,30 +185,37 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
180185 }
181186 }
182187
183- protected getUniqueFilterItems ( column : ColumnType , filterItems : IgxFilterItem [ ] ) {
184- const filteredUniqueValues = filterItems . reduce ( ( map , item ) => {
185- let key = item . value ;
186-
187- if ( column . dataType === GridColumnDataType . String && column . filteringIgnoreCase ) {
188- key = key ?. toString ( ) . toLowerCase ( ) ;
189- } else if ( column . dataType === GridColumnDataType . DateTime ) {
190- key = item . value ?. toString ( ) ;
191- item . value = key ? new Date ( key ) : key ;
192- } else if ( column . dataType === GridColumnDataType . Time ) {
193- const date = key ? new Date ( key ) : key ;
194- key = date ? new Date ( ) . setHours ( date . getHours ( ) , date . getMinutes ( ) , date . getSeconds ( ) , date . getMilliseconds ( ) ) : key ;
195- item . value = key ? new Date ( key ) : key ;
196- } else if ( column . dataType === GridColumnDataType . Date ) {
197- const date = key ? new Date ( key ) : key ;
198- key = date ? new Date ( date . getFullYear ( ) , date . getMonth ( ) , date . getDate ( ) ) . toISOString ( ) : key ;
199- item . value = date ;
200- }
201-
202- return map . has ( key ) ? map : map . set ( key , item )
203- } , new Map ( ) ) ;
204- const uniqueValues = Array . from ( filteredUniqueValues . values ( ) ) ;
188+ protected getFilterItemKeyValue ( value : any , column : ColumnType ) {
189+ let key : any = value ;
190+ let finalValue = value ;
191+ if ( column . dataType === GridColumnDataType . String && column . filteringIgnoreCase ) {
192+ key = key ?. toString ( ) . toLowerCase ( ) ;
193+ } else if ( column . dataType === GridColumnDataType . DateTime ) {
194+ key = value ?. toString ( ) ;
195+ finalValue = key ? new Date ( key ) : key ;
196+ } else if ( column . dataType === GridColumnDataType . Time ) {
197+ const date = key ? new Date ( key ) : key ;
198+ key = date
199+ ? new Date ( ) . setHours (
200+ date . getHours ( ) ,
201+ date . getMinutes ( ) ,
202+ date . getSeconds ( ) ,
203+ date . getMilliseconds ( )
204+ )
205+ : date ;
206+ finalValue = key ? new Date ( key ) : key ;
207+ } else if ( column . dataType === GridColumnDataType . Date ) {
208+ const date = key ? new Date ( key ) : key ;
209+ key = date
210+ ? new Date ( date . getFullYear ( ) , date . getMonth ( ) , date . getDate ( ) ) . toISOString ( )
211+ : date ;
212+ finalValue = date ;
213+ }
214+ return { key, finalValue } ;
215+ }
205216
206- return uniqueValues ;
217+ protected getRecord ( item : any ) {
218+ return item ;
207219 }
208220
209221 protected shouldFormatFilterValues ( _column : ColumnType ) : boolean {
0 commit comments