New to Kendo UI for Angular? Start a free 30-day trial

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.

Example
View Source
Change Theme:

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:

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:

ComponentDefault 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.

Example
View Source
Change Theme:

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.

Example
View Source
Change Theme:

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.

  1. Add a template tag with the kendoTreeListFilterMenuTemplate directive for the title column. Inside the template tag, place the MultiSelect component. Notice that the value of the MultiSelect component is composed from the provided filter descriptors through a custom pipe.

    <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>
  2. Handle the MultiSelect valueChange event and set the filter descriptor through the filterService instance.

    public 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.

Example
View Source
Change Theme:

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:

  1. Create a custom component that will take the filter of the current column and the TreeList FilterService as inputs, and place it within the FilterMenuTemplateDirective.

    <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>
  2. Use the passed filter value in the custom component to sync the filtering component value with the currently applied filter for the column.

  3. 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 the filter() method of the FilterService 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:

  1. Create a custom component that will take the filter of the current column and the FilterService as inputs and place it within the FilterMenuTemplateDirective.

    <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>
  2. Set the value of the DropDownList.

    public 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;
        }
    }
  3. Set the current column filter by calling the filter() function of the filterService.

    public 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.

Example
View Source
Change Theme:

Multi-Checkbox Menu Filtering

To create a custom multi-checkbox menu component and use it in the Filter Menu template of the TreeList:

  1. Create a custom component that will take the filter of the current column and the FilterService 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.

    <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>
  2. 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.

    <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>
  3. Monitor the selected items and call the filterService.filter() method accordingly.

    public 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'
        });
    }
  4. (Optional) Add a filtering feature for the list of options.

    <li *ngIf="showFilter">
        <kendo-textbox (valueChange)="onValueChange($event)"></kendo-textbox>
    </li>
    public 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.

Example
View Source
Change Theme:

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 TreeList 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.

Example
View Source
Change Theme: