Angular Tree Grid Filtering
IgniteUI for Angular Tree Grid component provides three different filtering types - Quick filtering, Excel style filtering and Advanced filtering which enable you to display only the records that meet specified criteria. The Material UI grid component in Ignite UI provides angular filter capabilities and extensive filtering API through the Data Container to which the Tree Grid is bound.
Angular Tree Grid Filtering Example
The sample below demonstrates Tree Grid's Quick filtering user experience. API filter() method is used to apply contains condition on the ProductName column through external igxInputGroup component.
Setup
In order to specify if filtering is enabled and which filtering mode should be used, the Tree Grid exposes the following boolean properties - allowFiltering
, allowAdvancedFiltering
, filterMode
and filterable
.
Property allowFiltering enables you to specify the following options:
- false - the filtering for the corresponding grid will be disabled; /default value/
- true - the filtering for the corresponding grid will be enabled;
Property allowAdvancedFiltering enables you to specify the following options:
- false - the advanced filtering for the corresponding grid will be disabled; /default value/
- true - the advanced filtering for the corresponding grid will be enabled;
Property filterMode enables you to specify the following options:
- quickFilter - a simplistic filtering UI; /default value/
- excelStyleFilter - an Excel-like filtering UI;
Property filterable enables you to specify the following options:
- true - the filtering for the corresponding column will be enabled; /default value/
- false - the filtering for the corresponding column will be disabled;
<igx-tree-grid [data]="data" [autoGenerate]="false" [allowFiltering]="true">
<igx-column field="Name" header="Order Product"></igx-column>
<igx-column field="Units" header="Units" dataType="number" [filterable]="false"></igx-column>
</igx-tree-grid>
To enable the Advanced filtering however, you need to set the allowAdvancedFiltering
input properties to true
.
<igx-tree-grid [data]="data" [autoGenerate]="true" [allowAdvancedFiltering]="true">
</igx-tree-grid>
Note
You can enable both the quickFilter
/excelStyleFilter
and the advanced filtering user interfaces in the Tree Grid. Both filtering user interfaces will work independently of one another. The final filtered result in the Tree Grid is the intersection between the results of the two filters.
Interaction
In order to open the filter row for a particular column, the 'Filter' chip below its header should be clicked. To add conditions you should choose filter operand using the dropdown on the left of the input and enter value. For number
and date
columns 'Equals' is selected by default, for string
- 'Contains' and for boolean
- 'All'. Pressing 'Enter' confirms the condition and you are now able to add another one. There is a dropdown, between 'condition' chips, which determines the logical operator between them, 'AND' is selected by default. To remove a condition you can click the 'X' button of the chip, and to edit it you should select the chip and the input will be populated with the chip's data. While filter row is opened you can click on any filterable column's header in order to select it and to be able to add filter conditions for it.
While some filtering conditions have been applied to a column, and the filter row is closed, you can either remove the conditions by clicking the chip's close button, or you can open the filter row by selecting any of the chips. When there is not enough space to show all the conditions, a filter icon is shown with a badge that indicates how many more conditions there are. It can also be clicked in order to open the filter row.
Usage
There's a default filtering strategy provided out of the box, as well as all the standard filtering conditions, which the developer can replace with their own implementation. In addition, we've provided a way to easily plug in your own custom filtering conditions. The Tree Grid currently provides not only a simplistic filtering UI, but also more complex filtering options. Depending on the set dataType
of the column, the correct set of filtering operations is loaded inside the filter UI dropdown. Additionally, you can set the ignoreCase
and the initial condition
properties.
Filtering feature is enabled for the Tree Grid component by setting the allowFiltering
input to true
. The default filterMode
is quickFilter
and it cannot be changed run time. To disable this feature for a certain column – set the filterable
input to false
.
<igx-tree-grid [data]="data" [autoGenerate]="false" [allowFiltering]="true">
<igx-column field="Name" header="Order Product"></igx-column>
<igx-column field="Units" header="Units" dataType="number"></igx-column>
<igx-column field="Delivered" header="Delivered" [dataType]="'boolean'" [filterable]="false">
</igx-tree-grid>
Note
If values of type string
are used by a column of dataType Date
, the Tree Grid won't parse them to Date
objects and using filtering conditions won't be possible. If you want to use string
objects, additional logic should be implemented on the application level, in order to parse the values to Date
objects.
You can filter any column or a combination of columns through the Tree Grid API. The Tree Grid exposes several methods for this task - filter
, filterGlobal
and clearFilter
.
filter
- filter a single column or a combination of columns.
There are five filtering operand classes exposed:
IgxFilteringOperand
: this is a base filtering operand, which can be inherited when defining custom filtering conditions.IgxBooleanFilteringOperand
defines all default filtering conditions forboolean
type.IgxNumberFilteringOperand
defines all default filtering conditions fornumeric
type.IgxStringFilteringOperand
defines all default filtering conditions forstring
type.IgxDateFilteringOperand
defines all default filtering conditions forDate
type.
// Single column filtering
// Filter the `Order Product` column for values which `contains` the `myproduct` substring, ignoring case
this.treeGrid.filter('Order Product', 'myproduct', IgxStringFilteringOperand.instance().condition('contains'), true);
The only required parameters are the column field key and the filtering term. Both the condition and the case sensitivity will be inferred from the column properties if not provided. In the case of multiple filtering, the method accepts an array of filtering expressions.
Note
The filtering operation DOES NOT change the underlying data source of the Tree Grid.
// Multi column filtering
const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And);
const productFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName');
const productExpression = {
condition: IgxStringFilteringOperand.instance().condition('contains'),
fieldName: 'Order Product',
ignoreCase: true,
searchVal: 'ch'
};
productFilteringExpressionsTree.filteringOperands.push(productExpression);
gridFilteringExpressionsTree.filteringOperands.push(productFilteringExpressionsTree);
const priceFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'Price');
const priceExpression = {
condition: IgxNumberFilteringOperand.instance().condition('greaterThan'),
fieldName: 'UnitPrice',
ignoreCase: true,
searchVal: 20
};
priceFilteringExpressionsTree.filteringOperands.push(priceExpression);
gridFilteringExpressionsTree.filteringOperands.push(priceFilteringExpressionsTree);
this.treeGrid.filteringExpressionsTree = gridFilteringExpressionsTree;
filterGlobal
- clears all existing filters and applies the new filtering condition to all Tree Grid's columns.
// Filter all cells for a value which contains `myproduct`
this.treeGrid.filteringLogic = FilteringLogic.Or;
this.treeGrid.filterGlobal('myproduct', IgxStringFilteringOperand.instance().condition('contains'), false);
clearFilter
- removes any applied filtering from the target column. If called with no arguments it will clear the filtering of all columns.
// Remove the filtering state from the ProductName column
this.treeGrid.clearFilter('Order Product');
// Clears the filtering state from all columns
this.treeGrid.clearFilter();
Initial filtered state
To set the initial filtering state of the Tree Grid, set the IgxTreeGridComponent
filteringExpressionsTree
property to an array of IFilteringExpressionsTree
for each column to be filtered.
constructor(private cdr: ChangeDetectorRef) { }
public ngAfterViewInit() {
const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And);
const productFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'Order Product');
const productExpression = {
condition: IgxStringFilteringOperand.instance().condition('contains'),
fieldName: 'Order Product',
ignoreCase: true,
searchVal: 'c'
};
productFilteringExpressionsTree.filteringOperands.push(productExpression);
gridFilteringExpressionsTree.filteringOperands.push(productFilteringExpressionsTree);
this.treeGrid.filteringExpressionsTree = gridFilteringExpressionsTree;
this.cdr.detectChanges();
}
Filtering logic
The filteringLogic
property of the Tree Grid controls how filtering multiple columns will resolve in the Tree Grid. You can change it at any time through the Tree Grid API, or through the Tree Grid input property.
import { FilteringLogic } from 'igniteui-angular';
// import { FilteringLogic } from '@infragistics/igniteui-angular'; for licensed package
...
this.treeGrid.filteringLogic = FilteringLogic.OR;
The default value of AND
returns only the rows that match all the currently applied filtering expressions. Following the example above, a row will be returned when both the 'ProductName' cell value contains 'myproduct' and the 'Price' cell value is greater than 55.
When set to OR
, a row will be returned when either the 'ProductName' cell value contains 'myproduct' or the 'Price' cell value is greater than 55.
Remote Filtering
The Tree Grid supports remote filtering, which is demonstrated in the Tree Grid Remote Data Operations
topic.
Custom Filtering Operands
You can customize the filtering menu by adding, removing or modifying the filtering operands. By default, the filtering menu contains certain operands based on the column’s data type (IgxBooleanFilteringOperand
, IgxDateFilteringOperand
, IgxNumberFilteringOperand
and IgxStringFilteringOperand
). You can extend these classes or their base class IgxFilteringOperand
to change the filtering menu items’ behavior.
In the sample below, inspect the "Order Product" and "Delivered" columns filters menus. For the "Delivered" column filter, we have limited the number of operands to All, True and False. For the "Order Product" column filter – we have modified the Contains and Does Not Contain operands logic to perform case sensitive search and added also Empty and Not Empty operands.
To do that, extend the IgxStringFilteringOperand
and IgxBooleanFilteringOperand
, modify the operations and their logic, and set the column filters
input to the new operands.
// grid-custom-filtering.component.ts
export class GridCustomFilteringComponent {
public caseSensitiveFilteringOperand = CaseSensitiveFilteringOperand.instance();
public booleanFilteringOperand = BooleanFilteringOperand.instance();
}
export class CaseSensitiveFilteringOperand extends IgxStringFilteringOperand {
private constructor() {
super();
const customOperations = [
{
iconName: 'contains',
isUnary: false,
logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
ignoreCase = false;
const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
return target.indexOf(search) !== -1;
},
name: 'Contains (case sensitive)'
},
{
iconName: 'does_not_contain',
isUnary: false,
logic: (target: string, searchVal: string, ignoreCase?: boolean) => {
ignoreCase = false;
const search = IgxStringFilteringOperand.applyIgnoreCase(searchVal, ignoreCase);
target = IgxStringFilteringOperand.applyIgnoreCase(target, ignoreCase);
return target.indexOf(search) === -1;
},
name: 'Does Not Contain (case sensitive)'
}
];
const emptyOperators = [
// 'Empty'
this.operations[6],
// 'Not Empty'
this.operations[7]
];
this.operations = customOperations.concat(emptyOperators);
}
}
export class BooleanFilteringOperand extends IgxBooleanFilteringOperand {
private constructor() {
super();
this.operations = [
// 'All'
this.operations[0],
// 'TRUE'
this.operations[1],
// 'FALSE'
this.operations[2]
];
}
}
<!-- tree-grid-filtering-custom-sample.component.html -->
<igx-tree-grid [data]="data" [autoGenerate]="false" [allowFiltering]="true">
<igx-column field="Name" header="Order Product" [filters]="caseSensitiveFilteringOperand"></igx-column>
<igx-column field="Delivered" header="Delivered" [dataType]="'boolean'" [filters]="booleanFilteringOperand">
<ng-template igxCell let-cell="cell" let-val>
<img *ngIf="val" src="assets/images/grid/active.png" title="Delivered" alt="Delivered" />
<img *ngIf="!val" src="assets/images/grid/expired.png" title="Undelivered" alt="Undelivered" />
</ng-template>
</igx-column>
</igx-tree-grid>
Re-templating filter cell
You can add a template marked with igxFilterCellTemplate
in order to retemplate the filter cell. In the sample below, an input is added for the string columns and IgxDatePicker for the date column. When the user types or selects a value, a filter with contains operator for string columns and equals operator for date columns, is applied using grid's public API.
Matching Records Only Filtering Strategy
By default, after a filtering is applied, the Tree Grid component displays the records matching the criterion that have been set and their parents in a grayed-out fashion to provide additional context. However, in some cases, you may want to display only the records matching particular filtering condition without any trace for their parents. This can be achieved by using the TreeGridMatchingRecordsOnlyFilteringStrategy
:
<igx-grid [data]="data" [allowFiltering]="true" [filterStrategy]="matchingRecordsOnlyStrategy">
</igx-grid>
import { TreeGridMatchingRecordsOnlyFilteringStrategy } from "igniteui-angular";
...
public matchingRecordsOnlyStrategy = new TreeGridMatchingRecordsOnlyFilteringStrategy();
Styling
To get started with styling the filtering row, we need to import the index
file, where all the theme functions and component mixins live:
@use "igniteui-angular/theming" as *;
// IMPORTANT: Prior to Ignite UI for Angular version 13 use:
// @import '~igniteui-angular/lib/core/styles/themes/index';
Following the simplest approach, we create a new theme that extends the grid-theme
and accepts the $filtering-row-text-color
, $filtering-row-background
, $filtering-header-text-color
and the $filtering-header-background
parameters.
$custom-grid: grid-theme(
$filtering-row-text-color: #292826,
$filtering-row-background: #FFCD0F,
$filtering-header-text-color: #292826,
$filtering-header-background: #FFCD0F
);
As seen, the grid-theme
only controls colors for the filtering row and the respective column header that is being filtered. We obviously have a lot more components inside the filtering row, such as an input group, chips, buttons and others. In order to style them, we need to create a separate theme for each one, so let's create a new input group theme and a new button theme:
$dark-input-group: input-group-theme(
$box-background: #FFCD0F,
$idle-text-color: #292826,
$focused-text-color: #292826,
$filled-text-color: #292826
);
$dark-button: button-theme(
$flat-background: #FFCD0F,
$flat-text-color: #292826,
$flat-hover-background: #292826,
$flat-hover-text-color: #FFCD0F
);
In this example we only changed some of the parameters for the input group and the button, but the input-group-theme
and the button-theme
provide way more parameters to control their respective styling.
The last step is to include the component mixins, each with its respective theme. We will also set the color property for the input's placeholder.
@include grid($custom-grid);
.igx-grid__filtering-row {
@include button($dark-button);
@include input-group($dark-input-group);
.igx-input-group__input::placeholder {
color: #FFCD0F;
}
}
Note
We scope the igx-button and the igx-input-group mixins within .igx-grid__filtering-row
, so that only the filtering row buttons and its input group would be styled. Otherwise other buttons and input groups in the grid would be affected too.
Note
If the component is using an Emulated
ViewEncapsulation, it is necessary to penetrate
this encapsulation using ::ng-deep
:
:host {
::ng-deep {
@include grid($custom-grid);
.igx-grid__filtering-row {
@include button($dark-button);
@include input-group($dark-input-group);
.igx-input-group__input::placeholder {
color: #FFCD0F;
}
}
}
}
Defining a color palette
Instead of hardcoding the color values like we just did, we can achieve greater flexibility in terms of colors by using the igx-palette
and igx-color
functions.
igx-palette
generates a color palette based on the primary and secondary colors that are passed:
$yellow-color: #FFCD0F;
$black-color: #292826;
$dark-palette: palette($primary: $black-color, $secondary: $yellow-color);
And then with igx-color
we can easily retrieve color from the palette.
$custom-grid: grid-theme(
$filtering-row-text-color: color($dark-palette, "primary", 400),
$filtering-row-background: color($dark-palette, "secondary", 400),
$filtering-header-text-color: color($dark-palette, "primary", 400),
$filtering-header-background: color($dark-palette, "secondary", 400)
);
$dark-input-group: input-group-theme(
$box-background: color($dark-palette, "secondary", 400),
$idle-text-color: color($dark-palette, "primary", 400),
$focused-text-color: color($dark-palette, "primary", 400),
$filled-text-color: color($dark-palette, "primary", 400)
);
$dark-button: button-theme(
$flat-background: color($dark-palette, "secondary", 400),
$flat-text-color: color($dark-palette, "primary", 400),
$flat-hover-background: color($dark-palette, "primary", 400),
$flat-hover-text-color: color($dark-palette, "secondary", 400)
);
Note
The igx-color
and igx-palette
are powerful functions for generating and retrieving colors. Please refer to Palettes
topic for detailed guidance on how to use them.
Using Schemas
Going further with the theming engine, you can build a robust and flexible structure that benefits from schemas. A schema is a recipe of a theme.
Extend one of the two predefined schemas, that are provided for every component, in this case - light-grid
, light-input-group
and light-button
schemas:
// Extending the light grid schema
$custom-grid-schema: extend($_light-grid,
(
filtering-row-text-color:(
color: ("primary", 400)
),
filtering-row-background:(
color: ("secondary", 400)
),
filtering-header-text-color:(
color: ("primary", 400)
),
filtering-header-background:(
color: ("secondary", 400)
)
)
);
// Extending the light input group schema
$custom-input-group-schema: extend($_light-input-group,
(
box-background:(
color: ("secondary", 400)
),
idle-text-color:(
color: ("primary", 400)
),
focused-text-color:(
color: ("primary", 400)
),
filled-text-color:(
color: ("primary", 400)
)
)
);
// Extending the light button schema
$custom-button-schema: extend($_light-button,
(
flat-background:(
color: ("secondary", 400)
),
flat-text-color:(
color: ("primary", 400)
),
flat-hover-background:(
color: ("primary", 400)
),
flat-hover-text-color:(
color: ("secondary", 400)
)
)
);
In order to apply our custom schemas we have to extend one of the globals (light
or dark
), which is basically pointing out the components with a custom schema, and after that add it to the respective component themes:
// Extending the global light-schema
$custom-light-schema: extend($light-schema,(
igx-grid: $custom-grid-schema,
igx-input-group: $custom-input-group-schema,
igx-button: $custom-button-schema
));
// Defining grid-theme with the global light schema
$custom-grid: grid-theme(
$palette: $dark-palette,
$schema: $custom-light-schema
);
// Defining button-theme with the global light schema
$custom-button: button-theme(
$palette: $dark-palette,
$schema: $custom-light-schema
);
// Defining input-group-theme with the global light schema
$custom-input-group: input-group-theme(
$palette: $dark-palette,
$schema: $custom-light-schema
);
Don't forget to include the themes in the same way as it was demonstrated above.
Demo
Note
The sample will not be affected by the selected global theme from Change Theme
.
Known Limitations
Note
Some browsers such as Firefox fail to parse regional specific decimal separators by considering them grouping separators, thus resulting in them being invalid. When inputting such values for a numeric column filter value, only the valid part of the number will be applied to the filtering expression. For further information, refer to the Firefox issue.
Breaking Changes in 6.1.0
- IgxTreeGrid
filteringExpressions
property is removed. UsefilteringExpressionsTree
instead. filter_multiple
method is removed. Usefilter
method andfilteringExpressionsTree
property instead.- The
filter
method has new signature. It now accepts the following parameters:name
- the name of the column to be filtered.value
- the value to be used for filtering.conditionOrExpressionTree
(optional) - this parameter accepts object of typeIFilteringOperation
orIFilteringExpressionsTree
. If only simple filtering is needed, a filtering operation could be passed as an argument. In case of advanced filtering, an expressions tree containing complex filtering logic could be passed as an argument.ignoreCase
(optional) - whether the filtering is case sensitive or not.
filteringDone
event now have only one parameter of typeIFilteringExpressionsTree
which contains the filtering state of the filtered column.- filtering operands:
IFilteringExpression
condition property is no longer a direct reference to a filtering condition method, instead it's a reference to anIFilteringOperation
. IgxColumnComponent
now exposes afilters
property, which takes anIgxFilteringOperand
class reference.- Custom filters can be provided to the Tree Grid columns by populating the
operations
property of theIgxFilteringOperand
with operations ofIFilteringOperation
type.
API References
Additional Resources
- Tree Grid overview
- Virtualization and Performance
- Paging
- Sorting
- Summaries
- Column Moving
- Column Pinning
- Column Resizing
- Selection