Skip to content

Commit 3374ac5

Browse files
committed
feat(h-grid): advanced filtering POC with sample
1 parent a7b6942 commit 3374ac5

File tree

11 files changed

+2092
-12
lines changed

11 files changed

+2092
-12
lines changed

projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,25 @@ export interface IgxFilterItem {
3939
export abstract class BaseFilteringStrategy implements IFilteringStrategy {
4040
// protected
4141
public findMatchByExpression(rec: any, expr: IFilteringExpression, isDate?: boolean, isTime?: boolean, grid?: GridType): boolean {
42+
if (expr.searchTree) {
43+
const records = rec[expr.searchTree.entity];
44+
for (let index = 0; index < records.length; index++) {
45+
const record = records[index];
46+
if (this.matchRecord(record, expr.searchTree, grid, expr.searchTree.entity)) {
47+
return true;
48+
}
49+
}
50+
51+
return false;
52+
}
53+
4254
const cond = expr.condition;
4355
const val = this.getFieldValue(rec, expr.fieldName, isDate, isTime, grid);
4456
return cond.logic(val, expr.searchVal, expr.ignoreCase);
4557
}
4658

4759
// protected
48-
public matchRecord(rec: any, expressions: IFilteringExpressionsTree | IFilteringExpression, grid?: GridType): boolean {
60+
public matchRecord(rec: any, expressions: IFilteringExpressionsTree | IFilteringExpression, grid?: GridType, entity?: string): boolean {
4961
if (expressions) {
5062
if (isTree(expressions)) {
5163
const expressionsTree = expressions;
@@ -54,7 +66,7 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
5466

5567
if (expressionsTree.filteringOperands && expressionsTree.filteringOperands.length) {
5668
for (const operand of expressionsTree.filteringOperands) {
57-
matchOperand = this.matchRecord(rec, operand, grid);
69+
matchOperand = this.matchRecord(rec, operand, grid, entity);
5870

5971
// Return false if at least one operand does not match and the filtering logic is And
6072
if (!matchOperand && operator === FilteringLogic.And) {
@@ -73,9 +85,16 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
7385
return true;
7486
} else {
7587
const expression = expressions;
76-
const column = grid && grid.getColumnByName(expression.fieldName);
77-
const isDate = column ? column.dataType === DateType || column.dataType === DateTimeType : false;
78-
const isTime = column ? column.dataType === TimeType : false;
88+
let isDate = false;
89+
let isTime = false;
90+
if (!entity) {
91+
const column = grid && grid.getColumnByName(expression.fieldName);
92+
isDate = column ? column.dataType === DateType || column.dataType === DateTimeType : false;
93+
isTime = column ? column.dataType === TimeType : false;
94+
} else {
95+
// TODO: check for date and time
96+
}
97+
7998
return this.findMatchByExpression(rec, expression, isDate, isTime, grid);
8099
}
81100
}

projects/igniteui-angular/src/lib/grids/common/grid.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,4 +1497,5 @@ export interface IClipboardOptions {
14971497
export interface EntityType {
14981498
name: string;
14991499
fields: FieldType[];
1500+
childEntities?: EntityType[];
15001501
}

projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IDragStartEventArgs, IgxDragDirective, IgxDragHandleDirective } from '.
66
import { Subject } from 'rxjs';
77
import { IActiveNode } from '../../grid-navigation.service';
88
import { PlatformUtil } from '../../../core/utils';
9-
import { FieldType, GridType } from '../../common/grid.interface';
9+
import { EntityType, FieldType, GridType } from '../../common/grid.interface';
1010
import { IgxQueryBuilderComponent } from '../../../query-builder/query-builder.component';
1111
import { GridResourceStringsEN } from '../../../core/i18n/grid-resources';
1212
import { IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree';
@@ -15,6 +15,8 @@ import { IgxQueryBuilderHeaderComponent } from '../../../query-builder/query-bui
1515
import { NgClass } from '@angular/common';
1616
import { getCurrentResourceStrings } from '../../../core/i18n/resources';
1717
import { QueryBuilderResourceStringsEN } from '../../../core/i18n/query-builder-resources';
18+
import { IgxHierarchicalGridComponent } from '../../hierarchical-grid/hierarchical-grid.component';
19+
import { IgxRowIslandComponent } from '../../hierarchical-grid/row-island.component';
1820

1921
/**
2022
* A component used for presenting advanced filtering UI for a Grid.
@@ -191,20 +193,69 @@ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDes
191193
this.closeDialog();
192194
}
193195

194-
196+
195197
/**
196198
* @hidden @internal
197199
*/
198200
public generateEntity() {
199-
const entities = [
201+
if (this.queryBuilder?.entities) {
202+
return this.queryBuilder?.entities;
203+
}
204+
205+
const isHierarchicalGrid = this.grid instanceof IgxHierarchicalGridComponent;
206+
const entities: EntityType[] = [
200207
{
201-
name: null,
202-
fields: this.filterableFields
208+
name: null,
209+
fields: this.filterableFields.map(f => ({ field: f.field, dataType: f.dataType })) as FieldType[]
203210
}
204211
];
212+
213+
if (isHierarchicalGrid) {
214+
const hierarchicalGrid = this.grid as IgxHierarchicalGridComponent;
215+
entities[0].childEntities = hierarchicalGrid.childLayoutList.reduce((acc, rowIsland) => {
216+
return acc.concat(this.generateChildEntity(rowIsland, hierarchicalGrid.data[0][rowIsland.key][0]));
217+
}
218+
, []);
219+
}
220+
205221
return entities;
206222
}
207223

224+
private generateChildEntity(rowIsland: IgxRowIslandComponent, firstRowData: any[]): EntityType {
225+
const entityName = rowIsland.key;
226+
let fields = [];
227+
let childEntities;
228+
if (!rowIsland.autoGenerate) {
229+
fields = rowIsland.columnList.map(f => ({ field: f.field, dataType: f.dataType })) as FieldType[];
230+
} else {
231+
const rowIslandFields = Object.keys(firstRowData).map(key => {
232+
if (firstRowData[key] instanceof Array) {
233+
return null;
234+
}
235+
236+
return {
237+
field: key,
238+
dataType: (this.grid as IgxHierarchicalGridComponent).resolveDataTypes(firstRowData[key])
239+
}
240+
});
241+
fields = rowIslandFields.filter(f => f !== null) as FieldType[];
242+
}
243+
244+
const rowIslandChildEntities = rowIsland.childLayoutList.reduce((acc, childRowIsland) => {
245+
return acc.concat(this.generateChildEntity(childRowIsland, firstRowData[childRowIsland.key][0]));
246+
}, []);
247+
248+
if (rowIslandChildEntities.length > 0) {
249+
childEntities = rowIslandChildEntities;
250+
}
251+
252+
return {
253+
name: entityName,
254+
fields: fields,
255+
childEntities: childEntities
256+
}
257+
}
258+
208259
private assignResourceStrings() {
209260
// If grid has custom resource strings set for the advanced filtering,
210261
// they are passed to the query builder resource strings.

projects/igniteui-angular/src/lib/query-builder/query-builder-tree.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@
453453
<ng-container>
454454
<igx-query-builder-tree
455455
[style.display]="expressionItem.inEditMode || expressionItem.expanded ? 'block' : 'none'"
456-
[entities]="entities"
456+
[entities]="(this.selectedEntity ? this.selectedEntity.childEntities : entities[0].childEntities) ?? entities"
457457
[queryBuilder]="this.queryBuilder"
458458
[parentExpression]="expressionItem"
459459
[expressionTree]="expressionItem.inEditMode ? (innerQueryNewExpressionTree ?? getExpressionTreeCopy(expressionItem.expression.searchTree, true)) : expressionItem.expression.searchTree"

projects/igniteui-angular/src/lib/query-builder/query-builder-tree.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,8 @@ export class IgxQueryBuilderTreeComponent implements AfterViewInit, OnDestroy {
13421342
public getConditionList(): string[] {
13431343
if (!this.selectedField) return [];
13441344

1345-
if (this.entities?.length === 1 && !this.entities[0].name) {
1345+
if ((this.entities?.length === 1 && !this.entities[0].name && !this.entities[0].childEntities) ||
1346+
(this.selectedEntity && this.selectedEntity.name && !this.selectedEntity.childEntities)) {
13461347
return this.selectedField.filters.conditionList();
13471348
}
13481349

src/app/app.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,10 @@ export class AppComponent implements OnInit {
576576
link: '/hierarchicalGrid',
577577
icon: 'view_column',
578578
name: 'Hierarchical Grid'
579+
}, {
580+
link: '/hierarchicalGridAdvancedFiltering',
581+
icon: 'view_column',
582+
name: 'Hierarchical Grid Advanced Filtering'
579583
}, {
580584
link: '/hierarchicalGridRemote',
581585
icon: 'swap_vert',

src/app/app.routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ import { GridDockManagerSampleComponent } from './dockmanager-grid/dockmanager-g
146146
import { HoundComponent } from './hound/hound.component';
147147
import { LabelSampleComponent } from "./label/label.sample";
148148
import { GridRecreateSampleComponent } from './grid-re-create/grid-re-create.sample';
149+
import { HierarchicalGridAdvancedFilteringSampleComponent } from './hierarchical-grid-advanced-filtering/hierarchical-grid-advanced-filtering.sample';
149150

150151
export const appRoutes: Routes = [
151152
{
@@ -616,6 +617,9 @@ export const appRoutes: Routes = [
616617
}, {
617618
path: 'hierarchicalGrid',
618619
component: HierarchicalGridSampleComponent
620+
}, {
621+
path: 'hierarchicalGridAdvancedFiltering',
622+
component: HierarchicalGridAdvancedFilteringSampleComponent
619623
}, {
620624
path: 'hierarchicalGridRemote',
621625
component: HierarchicalGridRemoteSampleComponent

0 commit comments

Comments
 (0)