Filtering

The KendoReact TreeList enables you to display only those TreeList records which meet specified criteria.

Getting Started

To enable filtering:

  1. Set the filter prop of the TreeList. The filtering conditions are declared as FilterDescriptors.
  2. Handle the onFilterChange or the onDataStateChange event of the TreeList, and filter the data manually or by using the filterBy function.
  3. Pass the component which will be responsible for the filtering of the column by using the filter prop.

Each consecutive filter is added to the previous ones and reduces the subset of data.

Filter Rows

By default, when filtering is enabled, the TreeList renders a filter row in its header. Based on the type of the filter component which is set in the filter prop of the columns, the filter row displays components in each column header where the user can filter string, numeric, boolean, or date inputs.

import React from 'react';
import ReactDOM from 'react-dom';
import {
    TreeList, filterBy, extendDataItem, mapTree,
    TreeListTextFilter, TreeListDateFilter, TreeListNumericFilter, TreeListBooleanFilter
} from '@progress/kendo-react-treelist';

import employees from './data';

const subItemsField = 'employees';
const expandField = 'expanded';
const columns = [
    { field: 'name', title: 'Name', width: 320, filter: TreeListTextFilter, expandable: true },
    { field: 'hireDate', title: 'Hire Date', width: 280, format: '{0:d}', filter: TreeListDateFilter },
    { field: 'timeInPosition', title: 'Year(s) in Position', width: 280, filter: TreeListNumericFilter },
    { field: 'fullTime', title: 'Full Time', width: 190, filter: TreeListBooleanFilter }
];

class App extends React.Component {
    state = {
        data: [ ...employees ],
        filter: [],
        expanded: [1, 2, 32]
    }

    onExpandChange = (e) => {
        this.setState({
            expanded: e.value ?
                this.state.expanded.filter(id => id !== e.dataItem.id) :
                [ ...this.state.expanded, e.dataItem.id ]
        });
    }

    handleFilterChange = (event) => {
        this.setState({
            filter: event.filter
        })
    }

    addExpandField = (dataTree) => {
        const expanded = this.state.expanded;
        return mapTree(dataTree, subItemsField, (item) =>
            extendDataItem(item, subItemsField, {
                [expandField]: expanded.includes(item.id)
            })
        );
    }

    processData = () => {
        let data = this.state.data;
        let filteredData = filterBy(data, this.state.filter, subItemsField)
        return this.addExpandField(filteredData);
    }

    render() {
        return (
            <TreeList
                style={{ maxHeight: '510px', overflow: 'auto' }}
                expandField={expandField}
                subItemsField={subItemsField}
                onExpandChange={this.onExpandChange}
                filter={this.state.filter}
                data={this.processData()}
                onFilterChange={this.handleFilterChange}
                columns={columns}
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Custom Filter Cells

The filter property of the TreeListColumn enables the full customization of the filter cells.

The following example demonstrates how to implement a filter by using the KendoReact DropDownList component.

import React from 'react';
import ReactDOM from 'react-dom';
import { TreeList, filterBy, extendDataItem, mapTree } from '@progress/kendo-react-treelist';
import DropDownFilter from './dropDownFilter.jsx';
import employees from './data';

const dropDownData = ['CEO', 'Technical Officer', 'Engineering', 'Team Lead', 'Software Developer', 'Software Architect', 'QA Engineer', 'Support Officer', 'UI Designer'];
const MyDropDownFilter = (props) => <DropDownFilter {...props} data={dropDownData} defaultItem="Select Position" />;

const columns = [
    { field: 'name', title: 'Name', width: 400, expandable: true },
    { field: 'position', title: 'Position', width: 300, filter: MyDropDownFilter },
    { field: 'hireDate', title: 'Hire Date', width: 300, format: '{0:d}' },
    { field: 'fullTime', title: 'Full Time', width: 300 }
];

const subItemsField = 'employees';
const expandField = 'expanded';

class App extends React.Component {
    state = {
        data: [ ...employees ],
        filter: [],
        expanded: [1, 2, 32]
    }

    onExpandChange = (e) => {
        this.setState({
            expanded: e.value ?
                this.state.expanded.filter(id => id !== e.dataItem.id) :
                [ ...this.state.expanded, e.dataItem.id ]
        });
    }

    handleFilterChange = (event) => {
        this.setState({
            filter: event.filter
        })
    }

    addExpandField = (dataTree) => {
        const expanded = this.state.expanded;
        return mapTree(dataTree, subItemsField, (item) =>
            extendDataItem(item, subItemsField, {
                [expandField]: expanded.includes(item.id)
            })
        );
    }

    processData = () => {
        let data = this.state.data;
        let filteredData = filterBy(data, this.state.filter, subItemsField)
        return this.addExpandField(filteredData);
    }

    render() {
        return (
            <TreeList
                style={{ maxHeight: '510px', overflow: 'auto' }}
                expandField={expandField}
                subItemsField={subItemsField}
                onExpandChange={this.onExpandChange}
                filter={this.state.filter}
                data={this.processData()}
                onFilterChange={this.handleFilterChange}
                columns={columns}
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
 /