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

Angular Grid Filter Row

The Grid enables you to embed a filter row above the column headers. To add a filter row to the Grid, set filterable to true.

The following example demonstrates the default filter row of the Grid.

Example
View Source
Change Theme:

Built-in Filter-Row Components

If you want to change the default appearance of the filtering UI, the FilterCellTemplateDirective comes handy.

The Grid package exposes the default filter-row UI for the basic data types as ready-for-use components. These components are especially useful when you need to customize the filter operators.

The following ready-for-use components are available to use inside the FilterCellTemplateDirective:

All built-in filter row components require you to bind the column and filter attributes to the template context.

<kendo-grid-column field="ProductName" title="Product Name">
    <ng-template kendoGridFilterCellTemplate let-filter let-column="column">
      <kendo-grid-string-filter-cell [column]="column" [filter]="filter">
      </kendo-grid-string-filter-cell>
    </ng-template>
</kendo-grid-column>

The built-in filter row components enable you to utilize the available configuration options and customize the filter settings of the Grid.

Default Filter Operator

The default operators for the built-in filter row components are:

ComponentDefault Operator
kendo-grid-boolean-filter-cell"eq"
kendo-grid-date-filter-cell"gte"
kendo-grid-numeric-filter-cell"eq"
kendo-grid-string-filter-cell"contains"

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 operators by setting the operator property of the built-in filter row components.

<kendo-grid-column field="ProductName" title="Product Name">
    <ng-template kendoGridFilterCellTemplate let-filter let-column="column">
      <kendo-grid-string-filter-cell [column]="column" [filter]="filter" operator="startswith">
          <kendo-filter-startswith-operator></kendo-filter-startswith-operator>
          <kendo-filter-eq-operator></kendo-filter-eq-operator>
      </kendo-grid-string-filter-cell>
    </ng-template>
</kendo-grid-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 adding operator components.

<kendo-grid-column field="ProductName" title="Product Name">
    <ng-template kendoGridFilterCellTemplate let-filter let-column="column">
      <kendo-grid-string-filter-cell [column]="column" [filter]="filter">
          <kendo-filter-contains-operator></kendo-filter-contains-operator>
          <kendo-filter-eq-operator></kendo-filter-eq-operator>
      </kendo-grid-string-filter-cell>
    </ng-template>
</kendo-grid-column>

The following example demonstrates how to set the order of operators.

Example
View Source
Change Theme:

Hiding Filter Operators

To hide the list of filter operators, set the showOperators option to false.

<kendo-grid-column field="ProductName" title="Product Name">
    <ng-template kendoGridFilterCellTemplate let-filter let-column="column">
      <kendo-grid-string-filter-cell
        [showOperators]="false"
        [column]="column"
        [filter]="filter">
      </kendo-grid-string-filter-cell>
    </ng-template>
</kendo-grid-column>

The following example demonstrates how to hide the filter operators.

Example
View Source
Change Theme:

Using Standalone Filter Operators Component

If you want to use the built-in filter operators along with any custom input control, define the FilterCellOperatorsComponent inside the kendoGridFilterCellTemplate directive.

To benefit from the built-in accessibility features of the Grid, pass the column context, provided by the template, to the column property of the filter operators component.

<ng-template kendoGridFilterCellTemplate let-filter let-column="column">
    <kendo-textbox> </kendo-textbox>
    <kendo-grid-filter-cell-operators
        [column]="column"
        [operators]="[{text: 'Equals', value: 'eq'}]">
    </kendo-grid-filter-cell-operators>
</ng-template>

The following example demonstrates the standalone filter operators component in action.

Example
View Source
Change Theme:

Custom Filters

The FilterCellTemplateDirective allows you to provide any custom content as a filtering UI. This feature is especially useful for scenarios in which the configuration options of the built-in filter row components aren't sufficient to achieve the desired result.

The following step-by-step guide demonstrates how to implement a custom boolean filter.

  1. Add a template tag with the kendoGridFilterCellTemplate directive for the boolean column and place a Switch component inside it.

    <kendo-grid-column field="Discontinued" [width]="120">
        <ng-template kendoGridFilterCellTemplate let-filter>
           <kendo-switch
               (valueChange)="switchChange($event)"
               offLabel="No"
               [checked]="checked"
               onLabel="Yes">
           </kendo-switch>
        </ng-template>
    </kendo-grid-column>
  2. Handle the Switch valueChange event and set the filter. Then call the filterChange method to notify the Grid that the filter has been modified.

    public switchChange(checked: boolean): void {
        const root = { logic: 'and', filters: [], ...this.filter };
        const [filter] = flatten(root).filter(x => x.field === "Discontinued");
    
        if (!filter) {
            root.filters.push({
                field: "Discontinued",
                operator: "eq",
                value: checked
            });
        } else {
            filter.value = checked;
        }
        this.checked = checked;
        this.filterChange(root);
    }

The following example demonstrates the full implementation of the approach.

Example
View Source
Change Theme:

Custom Filter Row Components

You can also create custom filtering components and use them within the FilterCellTemplateDirective. This scenario is suitable when you want to reuse the custom filtering UI across multiple Grid columns and/or many Grid components.

To implement a custom reusable filter row component in the Grid:

  1. Extend the base filter cell component from BaseFilterCellComponent to utilize the existing functions.

    export class MyCustomFilterComponent extends BaseFilterCellComponent {
        //...
    }
  2. Inject the FilterService through the constructor and pass it to the super call, as it is required by the BaseFilterCellComponent class. This service is responsible for the communication with the host Grid component.

    constructor(filterService: FilterService) {
        super(filterService);
    }
  3. Modify the root filter descriptor from within the custom filter-row component by using the applyFilter(), removeFilter(), and updateFilter() methods provided by the BaseFilterCellComponent. Their purpose is to update the root filter and to remove or override the child filter for the given field.

Using DropDownList

You can use the Kendo UI for Angular DropDownList in Grid and filter the data by choosing a single predefined value from a list.

Example
View Source
Change Theme:

To integrate the DropDownList component:

  1. Extend the BaseFilterCellComponent and pass a FilterService through the constructor.

    export class DropDownListFilterComponent extends BaseFilterCellComponent {
        constructor(filterService: FilterService) {
            super(filterService);
        }
    }
  2. Add the root CompositeFilterDescriptor as required by the component so you can add or modify it with the filter descriptor that will be built.

    @Input() public filter: CompositeFilterDescriptor;
  3. Provide the appropriate textField, valueField, and data input properties to reuse the filter component on different column fields. Pass the properties to the DropDownList component.

    @Input() public data: any[];
    @Input() public textField: string;
    @Input() public valueField: string;
  4. (Optional) Construct a default placeholder item that will be used when the user wants to remove the filter.

    public get defaultItem(): any {
        return {
            [this.textField]: "Select item...",
            [this.valueField]: null
        };
    }
  5. Add the DropDownList component to the template.

    @Component({
        selector: 'my-dropdown-filter',
        template: `
            <kendo-dropdownlist
                [data]="data"
                (valueChange)="onChange($event)"
                [defaultItem]="defaultItem"
                [value]="selectedValue"
                [valuePrimitive]="true"
                [textField]="textField"
                [valueField]="valueField">
            </kendo-dropdownlist>
        `
    })
    export class DropDownListFilterComponent extends BaseFilterCellComponent {
        //...
    }
  6. Hook the valueChange event handler and modify the root filter descriptor by using the applyFilter(), removeFilter(), and updateFilter() functions inherited from the base class.

    public onChange(value: any): void {
        this.applyFilter(
            value === null ? // if value of the default item
                this.removeFilter(this.valueField) : // remove the filter
                this.updateFilter({ // otherwise add/modify the filter for the field with the value
                    field: this.valueField,
                    operator: "eq",
                    value: value
                })
        ); // and update the root filter
    }
  7. Place the custom filter component in the filter cell template and hook it with the respective host component fields.

    <kendo-grid-column field="Category.CategoryName" title="Category">
        <ng-template kendoGridFilterCellTemplate let-filter>
            <my-dropdown-filter
                [filter]="filter"
                [data]="distinctCategories"
                textField="CategoryName"
                valueField="CategoryID">
            </my-dropdown-filter>
        </ng-template>
    </kendo-grid-column>

Using DateRange

The Grid enables you to implement custom filtering which is based on a given period between two dates.

Example
View Source
Change Theme:

To create a custom DateRange filter in Grid:

  1. Extend the BaseFilterCellComponent and pass a FilterService through the constructor.

    export class DateRangeFilterCellComponent extends BaseFilterCellComponent {
        constructor(filterService: FilterService) {
            super(filterService);
        }
    }
  2. Add the root CompositeFilterDescriptor as required by the component so you can add or modify it with the filter descriptor that will be built.

    @Input() public filter: CompositeFilterDescriptor;
  3. Add the DateRange component to the custom DateRangeFilterCellComponent template and handle the valueChange events of the respective DateInput components.

    <kendo-daterange>
        <kendo-dateinput
        kendoDateRangeStartInput
            [value]="start"
            (valueChange)="filterRange($event, end)">
        </kendo-dateinput>
        -
        <kendo-dateinput
            kendoDateRangeEndInput
            [value]="end"
            (valueChange)="filterRange(start, $event)">
        </kendo-dateinput>
    </kendo-daterange>
  4. Construct a CompositeFilterDescriptor which describes the selected date range and add it to the root filter of the Grid. Use the filterService to update the CompositeFilterDescriptor applied to the Grid.

    public filterRange(start: Date, end: Date): void {
        this.filter = this.removeFilter(this.field);
    
        const filters = [];
    
        if (start) {
            filters.push({
                field: this.field,
                operator: "gte",
                value: start
            });
        }
    
        if (end) {
            filters.push({
                field: this.field,
                operator: "lte",
                value: end
            });
        }
    
        const root: CompositeFilterDescriptor = this.filter || {
            logic: "and",
            filters: []
        };
    
        if (filters.length) {
            root.filters.push(...filters);
        }
    
        this.filterService.filter(root);
    }