Angular TreeList Filter Menu
The TreeList enables you to embed a drop-down filter menu in each column header. To add a filter menu to the TreeList, set filterable
to menu
.
The following example demonstrates the default filter menu of the TreeList.
Built-in Filter-Menu Components
To change the default appearance of any default filter menu UI, use the FilterMenuTemplateDirective
.
The TreeList 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-to-use components are available for the FilterMenuTemplateDirective
:
kendo-treelist-string-filter-menu
kendo-treelist-numeric-filter-menu
kendo-treelist-boolean-filter-menu
kendo-treelist-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-treelist-column field="name">
<ng-template kendoTreeListFilterMenuTemplate
let-filter
let-column="column"
let-filterService="filterService"
>
<kendo-treelist-string-filter-menu
[column]="column"
[filter]="filter"
[filterService]="filterService">
</kendo-treelist-string-filter-menu>
</ng-template>
</kendo-treelist-column>
The built-in filter menu components enable you to utilize the available configuration options and customize the filter settings of the TreeList at the same time.
Default Filter Operator
The default operators for the built-in filter menu components are:
Component | Default Operator |
---|---|
kendo-treelist-string-filter-menu | "contains" |
kendo-treelist-numeric-filter-menu | "eq" |
kendo-treelist-boolean-filter-menu | "eq" |
kendo-treelist-date-filter-menu | "gte" |
If
operator
is set to""
, the TreeList 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-treelist-column field="name" title="Name" [width]="180">
<ng-template kendoTreeListFilterMenuTemplate
let-filter
let-column="column"
let-filterService="filterService"
>
<kendo-treelist-string-filter-menu
[column]="column"
[filter]="filter"
[filterService]="filterService"
operator="startswith">
<kendo-treelist-filter-startswith-operator></kendo-treelist-filter-startswith-operator>
<kendo-treelist-filter-eq-operator></kendo-treelist-filter-eq-operator>
</kendo-treelist-string-filter-menu>
</ng-template>
</kendo-treelist-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-treelist-column field="name" title="Name" [width]="180">
<ng-template kendoTreeListFilterMenuTemplate
let-filter
let-column="column"
let-filterService="filterService"
>
<kendo-treelist-string-filter-menu
[column]="column"
[filter]="filter"
[filterService]="filterService">
<kendo-treelist-filter-eq-operator></kendo-treelist-filter-eq-operator>
<kendo-treelist-filter-contains-operator></kendo-treelist-filter-contains-operator>
</kendo-treelist-string-filter-menu>
</ng-template>
</kendo-treelist-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 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
kendoTreeListFilterMenuTemplate
directive for thetitle
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-treelist-column field="title" title="Title" [width]="180"> <ng-template kendoTreeListFilterMenuTemplate let-column="column" let-filter="filter" let-filterService="filterService" > <kendo-multiselect style="width:220px" [data]="titles" [valuePrimitive]="true" [value]="titleFilters(filter)" (valueChange)="titleChange($event, filterService)" > </kendo-multiselect> </ng-template> </kendo-treelist-column>
-
Handle the MultiSelect
valueChange
event and set the filter descriptor through thefilterService
instance.tspublic titleChange(values: unknown[], filterService: FilterService): void { filterService.filter({ filters: values.map(value => ({ field: 'title', 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 TreeList columns as well as across multiple TreeList instances throughout the application.
To implement a reusable filter menu component in the TreeList:
-
Create a custom component that will take the
filter
of the current column and the TreeListFilterService
as inputs, and place it within theFilterMenuTemplateDirective
.html<kendo-treelist-column field="title" title="Title" [width]="180"> <ng-template kendoTreeListFilterMenuTemplate let-filter="filter" let-filterService="filterService" > <my-custom-filter-menu-component [currentFilter]="filter" [filterService]="filterService"> </my-custom-filter-menu-component> </ng-template> </kendo-treelist-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 TreeList filters by passing a
CompositeFilterDescriptor
to thefilter()
method of theFilterService
instance.
Custom DropDownList Filter Menu Component
You can use the Kendo UI for Angular DropDownList in the TreeList and filter the data by choosing a single predefined value from a list. To integrate the DropDownList 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-treelist-column field="title" title="Title" [width]="180"> <ng-template kendoTreeListFilterMenuTemplate let-filter="filter" let-filterService="filterService" > <my-dropdown-filter [filter]="filter" [filterService]="filterService" [data]="titles" field="title" textField="text" valueField="value"> </my-dropdown-filter> </ng-template> </kendo-treelist-column>
-
Set the value of the DropDownList.
tspublic ngAfterViewInit(): void { this.currentData = this.data; const currentColumnFilter: any = this.filter.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); this.value = value; }
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 Filter Menu template of the TreeList:
-
Create a custom component that will take the
filter
of the current column and theFilterService
as inputs. Use a collection of the distinct TreeList records for the respective field as data. The custom filter component can work with both primitive values and complex objects.html<kendo-treelist-column field="name" title="Name"> <ng-template kendoTreeListFilterMenuTemplate 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-treelist-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 TreeList column. Attach the required handlers and bindings that will manage the selection and deselection of items.
html<ul> <li *ngIf="showFilter"> <kendo-textbox (valueChange)="onValueChange($event)"></kendo-textbox> </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]}}" kendoCheckBox [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"> <kendo-textbox (valueChange)="onValueChange($event)"></kendo-textbox> </li>
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 its container. This behavior can cause issues when using components like the DatePicker, which open their own popups. For example, clicking the DatePicker's calendar popup will close the TreeList filter menu.
To prevent the filter menu from closing, you can override the default behavior by following these steps:
- Inject the
SinglePopupService
in the custom filter component to manage the popup behavior. - Subscribe to the
onClose
event to intercept the filter menu's closing. - Check if the active element is part of the filter menu or a related popup (for example DatePicker). If so, prevent the default closing behavior.
// custom-filter-menu.component.ts
constructor(private element: ElementRef, private popupService: SinglePopupService) {
popupService.onClose.subscribe(
(e: PopupCloseEvent) => {
if (/* check the active element */) {
e.preventDefault();
}
}
);
}
The following example demonstrates how to keep the filter menu open while interacting with a DatePicker popup.