Angular Grid Filter Menu
The Grid enables you to embed a drop-down filter menu in each column header. To add a filter menu to the Grid, set filterable
to menu
.
The following example demonstrates the default filter menu of the Grid.
Built-in Filter-Menu Components
If you want to change the default appearance of any default filter menu UI, the FilterMenuTemplateDirective
comes handy.
The Grid package provides default filter menu UI components for the most common data types—string
, number
, Date
, and boolean
. These components are useful when you apply specific configurations to the default filter menu UI, modify the filter operators, and so on.
The following ready-for-use components are available for the FilterMenuTemplateDirective
:
- kendo-grid-string-filter-menu
- kendo-grid-numeric-filter-menu
- kendo-grid-boolean-filter-menu
- kendo-grid-date-filter-menu
All built-in filter menu components require you to bind the column
, filter
, and filterService
input options to the respective template context properties.
<kendo-grid-column field="ProductName" title="Product Name">
<ng-template kendoGridFilterMenuTemplate let-filter let-column="column" let-filterService="filterService">
<kendo-grid-string-filter-menu [column]="column" [filter]="filter" [filterService]="filterService">
</kendo-grid-string-filter-menu>
</ng-template>
</kendo-grid-column>
The built-in filter menu components enable you to utilize the available configuration options and customize the filter settings of the Grid at the same time.
Default Filter Operator
The default operators for the built-in filter menu components are:
Component | Default Operator |
---|---|
kendo-grid-string-filter-menu | "contains" |
kendo-grid-numeric-filter-menu | "eq" |
kendo-grid-boolean-filter-menu | "eq" |
kendo-grid-date-filter-menu | "gte" |
If
operator
is set to""
, the Grid will use the first operator from the defined list of operators as its default operator.
You can override the default filter operator by setting the operator
property of the built-in filter menu components.
<kendo-grid-column field="ProductName" title="Product Name">
<ng-template kendoGridFilterMenuTemplate let-filter let-column="column" let-filterService="filterService">
<kendo-grid-string-filter-menu
[column]="column"
[filter]="filter"
[filterService]="filterService"
operator="startswith">
<kendo-filter-startswith-operator></kendo-filter-startswith-operator>
<kendo-filter-eq-operator></kendo-filter-eq-operator>
</kendo-grid-string-filter-menu>
</ng-template>
</kendo-grid-column>
The following example demonstrates how to configure a string filter with a default startswith
operator.
Order of Filter Operators
You can manually fine-tune the order and number of available operators by declaring the desired operator components in the template.
<kendo-grid-column field="ProductName" title="Product Name">
<ng-template kendoGridFilterMenuTemplate let-filter let-column="column" let-filterService="filterService">
<kendo-grid-string-filter-menu
[column]="column"
[filter]="filter"
[filterService]="filterService">
<kendo-filter-contains-operator></kendo-filter-contains-operator>
<kendo-filter-eq-operator></kendo-filter-eq-operator>
</kendo-grid-string-filter-menu>
</ng-template>
</kendo-grid-column>
The following example demonstrates how to set the order of operators.
Custom Filters
The filter menu template also allows you to add any custom content—HTML elements and/or Angular components. This feature is especially useful for scenarios in which the configuration options of the built-in filter menu components are not sufficient to achieve the desired result.
The following steps demonstrate how to implement a custom multi-select filter.
-
Add a template tag with the
kendoGridFilterMenuTemplate
directive for theCategoryID
column. Inside the template tag, place the MultiSelect component. Notice that thevalue
of the MultiSelect component is composed from the provided filter descriptors through a custom pipe.html<kendo-grid-column field="CategoryID" title="Category" [width]="180"> <ng-template kendoGridFilterMenuTemplate let-column="column" let-filter="filter" let-filterService="filterService" > <kendo-multiselect style="width:220px" [data]="categories" textField="CategoryName" valueField="CategoryID" [valuePrimitive]="true" [value]="filter | filterValues" (valueChange)="categoryChange($event, filterService)" > </kendo-multiselect> </ng-template> ... </kendo-grid-column>
-
Handle the MultiSelect
valueChange
event and set the filter descriptor through thefilterService
instance.tspublic categoryChange(values: string[], filterService: FilterService): void { filterService.filter({ filters: values.map(value => ({ field: "CategoryID", operator: "eq", value })), logic: "or" }); }
The following example demonstrates the full implementation of this approach.
Custom Filter Menu Components
You can also create custom filter components and use them within the FilterMenuTemplateDirective
. This scenario is suitable when the content of the FilterMenuTemplateDirective
must be extracted to a component that can be reused in multiple Grid columns as well as across multiple Grid instances throughout the application.
To implement a reusable filter menu component in the Grid:
-
Create a custom component that will take the
filter
of the current column and the GridFilterService
as inputs, and place it within theFilterMenuTemplateDirective
.html<kendo-grid-column field="ProductName" title="Product Name" [width]="200"> <ng-template kendoGridFilterMenuTemplate let-filter="filter" let-filterService="filterService"> <my-custom-filter-menu-component [currentFilter]="filter" [filterService]="filterService"> </my-custom-filter-menu-component> </ng-template> </kendo-grid-column>
-
Use the passed
filter
value in the custom component to sync the filtering component value with the currently applied filter for the column. -
Within the custom filter-menu component, on a user-defined event (typically the component's value change event), update the Grid filters by passing a
CompositeFilterDescriptor
to thefilter()
method of theFilterService
instance.
Custom DropDownList Filter Menu Component
-
Create a custom component that will take the
filter
of the current column and theFilterService
as inputs and place it within theFilterMenuTemplateDirective
.html<kendo-grid-column field="ProductName" title="Product Name" [width]="200"> <ng-template kendoGridFilterMenuTemplate let-column="column" let-filter="filter" let-filterService="filterService" > <dropdownlist-filter [isPrimitive]="true" [field]="column.field" [currentFilter]="filter" [filterService]="filterService" [textField]="column.field" [valueField]="column.field" [data]="distinctPrimitive(column.field)"> </dropdownlist-filter> </ng-template> </kendo-grid-column>
-
Set the value of the DropDownList.
tspublic ngAfterViewInit(): void { this.currentData = this.data; const currentColumnFilter: FilterDescriptor = this.currentFilter.filters.find( (filter: FilterDescriptor) => filter.field === this.field ); if (currentColumnFilter) { this.value = currentColumnFilter.value; } }
-
Set the current column filter by calling the
filter()
function of thefilterService
.tspublic onValueChange(value: number): void { const myFilter: CompositeFilterDescriptor = { filters: [{ field: this.field, operator: 'eq', value: value }], logic: 'and', }; this.filterService.filter(myFilter); }
The following example demonstrates how to create reusable Filter Menu component that contains a DropDownList.
Multi-Checkbox Menu Filtering
To create a custom multi-checkbox menu component and use it in the FilterMenu template of the Grid:
-
Create a custom component that will take the
filter
of the current column and theFilterService
as inputs. Use a collection of the distinct Grid records for the respective field as data. The custom filter component can work with both primitive values and complex objects.html<kendo-grid-column field="ProductName" title="Product Name"> <ng-template kendoGridFilterMenuTemplate let-column="column" let-filter="filter" let-filterService="filterService" > <multicheck-filter [isPrimitive]="true" [field]="column.field" [filterService]="filterService" [currentFilter]="filter" [data]="distinctPrimitive(column.field)"></multicheck-filter> </ng-template> </kendo-grid-column>
-
Loop through the data to create a list of items with checkboxes and text. The items will correspond to the values of the respective Grid column. Attach the required handlers and bindings that will manage the selection and deselection of items.
html<ul> <li *ngIf="showFilter"> <input class="k-textbox k-input k-rounded-md" (input)="onInput($event)" /> </li> <li *ngFor="let item of currentData; let i = index;" (click)="onSelectionChange(isPrimitive ? item : item[valueField])" [ngClass]="{'k-selected': isItemSelected(item)}"> <input type="checkbox" id="chk-{{isPrimitive ? item : item[valueField]}}" [checked]="isItemSelected(item)" /> <label class="k-multiselect-checkbox k-checkbox-label" for="chk-{{isPrimitive ? item : item[valueField]}}"> {{ isPrimitive ? item : item[textField] }} </label> </li> </ul>
-
Monitor the selected items and call the
filterService.filter()
method accordingly.tspublic onSelectionChange(item) { if(this.value.some(x => x === item)) { this.value = this.value.filter(x => x !== item); } else { this.value.push(item); } this.filterService.filter({ filters: this.value.map(value => ({ field: this.field, operator: 'eq', value })), logic: 'or' }); }
-
(Optional) Add a filtering feature for the list of options.
html<li *ngIf="showFilter"> <input class="k-textbox k-input k-rounded-md" (input)="onInput($event)" /> </li>
tspublic onInput(e) { this.currentData = distinct([ ...this.currentData.filter(dataItem => this.value.some(val => val === this.valueAccessor(dataItem))), ...filterBy(this.data, { operator: 'contains', field: this.textField, value: e.target.value })], this.textField ); }
The following example demonstrates the full implementation of the described approach.
Filter Menu with Popup
By default, the filter menu closes when the user clicks outside the menu container. This leads to undesired behavior when using components that open their own popups in the body or the root component—for example, the DatePicker. Clicking in the DatePicker's calendar popup will close the Grid filter menu.
To avoid this, override the default behavior and prevent the menu from closing by injecting the SinglePopupService into the current filter component. Then prevent its onClose event.
The following example demonstrates the suggested approach.