diff --git a/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts
index 02a8c260a46..c9543362999 100644
--- a/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts
+++ b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts
@@ -150,7 +150,7 @@ function recreateExpression(expression: IFilteringExpression, fields: FieldType[
}
if (!expression.condition && expression.conditionName) {
- throw Error('Wrong `conditionName`, `condition` or `field` provided!');
+ throw Error('Wrong `conditionName`, `condition` or `field` provided! It is possible that there is a type mismatch between the condition type and field type.');
}
if (!expression.conditionName) {
diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts
index 97d9b870c99..edf766bffcc 100644
--- a/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts
+++ b/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts
@@ -908,7 +908,7 @@ export interface IFilteringOperation {
hidden?: boolean;
/* blazorCSSuppress */
/* blazorAlternateType: FilteringOperationLogicHandler */
- logic: (value: any, searchVal?: any, ignoreCase?: boolean) => boolean;
+ logic?: null | ((value: any, searchVal?: any, ignoreCase?: boolean) => boolean);
}
/**
diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts
index 3e308e0fe1c..dfb3212e810 100644
--- a/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts
+++ b/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts
@@ -14,9 +14,9 @@ export enum FilteringLogic {
*/
export declare interface IFilteringExpression {
fieldName: string;
- condition?: IFilteringOperation;
- conditionName?: string;
+ condition?: IFilteringOperation | null;
+ conditionName?: string | null;
searchVal?: any;
- searchTree?: IExpressionTree;
+ searchTree?: IExpressionTree | null;
ignoreCase?: boolean;
}
diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts
index 1381263f5bf..229050379b4 100644
--- a/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts
+++ b/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts
@@ -11,9 +11,9 @@ export enum FilteringExpressionsTreeType {
export declare interface IExpressionTree {
filteringOperands: (IExpressionTree | IFilteringExpression)[];
operator: FilteringLogic;
- fieldName?: string;
- entity?: string;
- returnFields?: string[];
+ fieldName?: string | null;
+ entity?: string | null;
+ returnFields?: string[] | null;
}
/* marshalByValue */
diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
index aa442dff801..0b346c079b5 100644
--- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
+++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
@@ -1856,8 +1856,8 @@ export abstract class IgxGridBaseDirective implements GridType,
}
value.type = FilteringExpressionsTreeType.Regular;
- if (value && this.columns) {
- this._filteringExpressionsTree = recreateTreeFromFields(value, this.columns) as IFilteringExpressionsTree;
+ if (value && this._columns?.length > 0) {
+ this._filteringExpressionsTree = recreateTreeFromFields(value, this._columns) as IFilteringExpressionsTree;
} else {
this._filteringExpressionsTree = value;
}
@@ -1906,7 +1906,11 @@ export abstract class IgxGridBaseDirective implements GridType,
if (value && isTree(value)) {
value.type = FilteringExpressionsTreeType.Advanced;
- this._advancedFilteringExpressionsTree = recreateTreeFromFields(value, this.columns) as IFilteringExpressionsTree;
+ if (this._columns && this._columns.length > 0) {
+ this._advancedFilteringExpressionsTree = recreateTreeFromFields(value, this._columns) as IFilteringExpressionsTree;
+ } else {
+ this._advancedFilteringExpressionsTree = value;
+ }
this.filteringPipeTrigger++;
} else {
this._advancedFilteringExpressionsTree = null;
@@ -6607,6 +6611,9 @@ export abstract class IgxGridBaseDirective implements GridType,
if (this._columns && this._filteringExpressionsTree) {
this._filteringExpressionsTree = recreateTreeFromFields(this._filteringExpressionsTree, this.columns) as IFilteringExpressionsTree;
}
+ if (this._columns && this._advancedFilteringExpressionsTree) {
+ this._advancedFilteringExpressionsTree = recreateTreeFromFields(this._advancedFilteringExpressionsTree, this.columns) as IFilteringExpressionsTree;
+ }
this.resetCaches();
}
@@ -6668,9 +6675,12 @@ export abstract class IgxGridBaseDirective implements GridType,
this.autogenerateColumns();
} else {
this._columns = this.getColumnList();
- if (this._columns && this._filteringExpressionsTree) {
- this._filteringExpressionsTree = recreateTreeFromFields(this._filteringExpressionsTree, this._columns) as IFilteringExpressionsTree;
- }
+ }
+ if (this._columns && this._filteringExpressionsTree) {
+ this._filteringExpressionsTree = recreateTreeFromFields(this._filteringExpressionsTree, this._columns) as IFilteringExpressionsTree;
+ }
+ if (this._columns && this._advancedFilteringExpressionsTree) {
+ this._advancedFilteringExpressionsTree = recreateTreeFromFields(this._advancedFilteringExpressionsTree, this._columns) as IFilteringExpressionsTree;
}
this.initColumns(this._columns, (col: IgxColumnComponent) => this.columnInit.emit(col));
diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts
index aaed44fe8c8..9fb2b661cfe 100644
--- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts
+++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts
@@ -16,6 +16,7 @@ import {
IgxGridExternalAdvancedFilteringComponent,
IgxGridAdvancedFilteringBindingComponent,
IgxGridAdvancedFilteringDynamicColumnsComponent,
+ IgxGridAdvancedFilteringSerializedTreeComponent,
IgxGridAdvancedFilteringWithToolbarComponent
} from '../../test-utils/grid-samples.spec';
import { FormattedValuesFilteringStrategy } from '../../data-operations/filtering-strategy';
@@ -1450,6 +1451,52 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => {
// Verify no filtered data
expect(grid.filteredData).toBe(null);
}));
+
+ });
+
+ describe('Expression tree rehydration - ', () => {
+ it('should correctly filter with a deserialized expression tree.', fakeAsync(() => {
+ const errorSpy = spyOn(console, 'error');
+ let fix = TestBed.createComponent(IgxGridAdvancedFilteringSerializedTreeComponent);
+ fix.detectChanges();
+ let grid = fix.componentInstance.grid;
+
+ expect(errorSpy).not.toHaveBeenCalled();
+
+ // Verify filtered data
+ expect(grid.filteredData.length).toEqual(3);
+ expect(grid.rowList.length).toBe(3);
+ }));
+
+ it('should correctly filter with a declared IFilteringExpressionsTree object.', fakeAsync(() => {
+ const errorSpy = spyOn(console, 'error');
+ let fix = TestBed.createComponent(IgxGridAdvancedFilteringSerializedTreeComponent);
+ fix.detectChanges();
+ fix.componentInstance.grid.advancedFilteringExpressionsTree = fix.componentInstance.filterTreeObject;
+ fix.detectChanges();
+ let grid = fix.componentInstance.grid;
+
+ expect(errorSpy).not.toHaveBeenCalled();
+
+ // Verify filtered data
+ expect(grid.filteredData.length).toEqual(2);
+ expect(grid.rowList.length).toBe(2);
+ }));
+
+ it('should correctly filter when binding to a declared IFilteringExpressionsTree object.', fakeAsync(() => {
+ const errorSpy = spyOn(console, 'error');
+ let fix = TestBed.createComponent(IgxGridAdvancedFilteringSerializedTreeComponent);
+ fix.detectChanges();
+ fix.componentInstance.filterTree = fix.componentInstance.filterTreeObject;
+ fix.detectChanges();
+ let grid = fix.componentInstance.grid;
+
+ expect(errorSpy).not.toHaveBeenCalled();
+
+ // Verify filtered data
+ expect(grid.filteredData.length).toEqual(2);
+ expect(grid.rowList.length).toBe(2);
+ }));
});
});
diff --git a/projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts b/projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts
index 2579254dc7f..e4ebe0c5ef7 100644
--- a/projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts
+++ b/projects/igniteui-angular/src/lib/test-utils/grid-samples.spec.ts
@@ -2100,6 +2100,61 @@ export class IgxGridAdvancedFilteringBindingComponent extends BasicGridComponent
}
}
+@Component({
+ template: `
+
+
+
+
+
+
+ `,
+ imports: [IgxGridComponent, IgxColumnComponent]
+})
+export class IgxGridAdvancedFilteringSerializedTreeComponent extends BasicGridComponent implements OnInit {
+ public resizable = false;
+ public filterable = true;
+ public filterTree: IFilteringExpressionsTree;
+ public filterTreeObject: IFilteringExpressionsTree;
+
+ public override data = SampleTestData.excelFilteringData();
+
+ public ngOnInit(): void {
+ this.filterTree = JSON.parse(`{
+ "filteringOperands": [
+ {
+ "conditionName": "greaterThan",
+ "fieldName": "Downloads",
+ "searchVal": 200
+ }
+ ],
+ "operator": 0
+ }`);
+
+ this.filterTreeObject = {
+ "filteringOperands": [
+ {
+ "fieldName": "ProductName",
+ "condition": {
+ "name": "contains",
+ "isUnary": false,
+ "iconName": "filter_contains"
+ },
+ "conditionName": "contains",
+ "ignoreCase": true,
+ "searchVal": "Ig",
+ "searchTree": null
+ }
+ ],
+ "operator": 1,
+ "returnFields": [
+ "ID",
+ "ProductName"
+ ]
+ };
+ }
+}
+
@Component({
template: `