New to Telerik UI for Blazor? Download free 30-day trial

TreeList Filter Menu

One of the filter modes of the treelist is a popup menu with filter options that you can open from the column headers.

In this article:

Basics

To enable the filter menu, set the FilterMode property of the grid to Telerik.Blazor.TreeListFilterMode.FilterMenu.

The treelist will render a button in the column header that you click to get a popup with filtering options. The popup lets you choose filter operator, filter criteria, to apply and clear the filter.

A key difference in the behavior from the filter row is that the filter is now applied only upon a button click, not upon input change. This may improve performance with large data sets.

Filter Menu in Telerik TreeList

@* Filter menu in the column header *@

<TelerikTreeList Data="@Data" FilterMode="@TreeListFilterMode.FilterMenu"
                 Pageable="true" IdField="Id" ParentIdField="ParentId" Width="650px">
    <TreeListColumns>
        <TreeListColumn Field="Name" Expandable="true" Width="320px"></TreeListColumn>
        <TreeListColumn Field="Id"></TreeListColumn>
    </TreeListColumns>
</TelerikTreeList>

@code {
    public List<Employee> Data { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Data = await GetTreeListData();
    }

    // sample models and data generation

    public class Employee
    {
        public int Id { get; set; }
        public int? ParentId { get; set; }
        public string Name { get; set; }
    }

    async Task<List<Employee>> GetTreeListData()
    {
        List<Employee> data = new List<Employee>();

        for (int i = 1; i < 15; i++)
        {
            data.Add(new Employee
            {
                Id = i,
                ParentId = null,
                Name = $"root: {i}"
            });

            for (int j = 2; j < 5; j++)
            {
                int currId = i * 100 + j;
                data.Add(new Employee
                {
                    Id = currId,
                    ParentId = i,
                    Name = $"first level child of {i}"
                });

                for (int k = 3; k < 5; k++)
                {
                    data.Add(new Employee
                    {
                        Id = currId * 1000 + k,
                        ParentId = currId,
                        Name = $"second level child {k} of {i} and {currId}"
                    }); ;
                }
            }
        }

        return await Task.FromResult(data);
    }
}

The result from the code snippet above, after the "Name" column has been filtered with "does not contain" "1" operator.

Blazor TreeList Filter Menu

Filter From Code

You can set the TreeList filters from your code through the component state.

If you want to set an initial state to the TreeList, use a similar snippet, but in the OnStateInit event

Set filtering programmatically

@* This snippet shows how to set filtering state to the TreeList from your code
  Applies to the FilterMenu mode *@

@using Telerik.DataSource;

<TelerikButton OnClick="@SetTreeListFilter">Set filtered state</TelerikButton>

<TelerikTreeList Data="@Data"
                 ItemsField="@(nameof(Employee.DirectReports))"
                 Reorderable="true"
                 Resizable="true"
                 Sortable="true"
                 FilterMode="@TreeListFilterMode.FilterMenu"
                 Pageable="true" 
                 Width="850px" 
                 @ref="TreeListRef">
    <TreeListColumns>
        <TreeListColumn Field="Name" Expandable="true" Width="320px" />
        <TreeListColumn Field="Id" Editable="false" Width="120px" />
        <TreeListColumn Field="EmailAddress" Width="220px" />
        <TreeListColumn Field="HireDate" Width="220px" />
    </TreeListColumns>
</TelerikTreeList>

@code {
    public TelerikTreeList<Employee> TreeListRef { get; set; } = new TelerikTreeList<Employee>();

    async Task SetTreeListFilter()
    {
        var filteredState = new TreeListState<Employee>()
        {
            FilterDescriptors = new List<IFilterDescriptor>()
            {
                new CompositeFilterDescriptor(){
                    FilterDescriptors = new FilterDescriptorCollection()
                    {
                        new FilterDescriptor()
                        {
                            Member = nameof(Employee.Id),
                            MemberType = typeof(int),
                            Operator = FilterOperator.IsGreaterThan,
                            Value = 5
                        }
                    }
                },
                new CompositeFilterDescriptor(){
                    FilterDescriptors = new FilterDescriptorCollection()
                    {
                        new FilterDescriptor()
                        {
                            Member = nameof(Employee.Name),
                            MemberType = typeof(string),
                            Operator = FilterOperator.Contains,
                            Value = "second level"
                        }
                    }
                },

            }
        };

        await TreeListRef.SetStateAsync(filteredState);
    }

    public List<Employee> Data { get; set; }

    // sample model

    public class Employee
    {
        // hierarchical data collections
        public List<Employee> DirectReports { get; set; }

        // data fields for display
        public int Id { get; set; }
        public string Name { get; set; }
        public string EmailAddress { get; set; }
        public DateTime HireDate { get; set; }
    }

    // data generation

    // used in this example for data generation and retrieval for CUD operations on the current view-model data
    public int LastId { get; set; } = 1;

    protected override async Task OnInitializedAsync()
    {
        Data = await GetTreeListData();
    }

    async Task<List<Employee>> GetTreeListData()
    {
        List<Employee> data = new List<Employee>();

        for (int i = 1; i < 15; i++)
        {
            Employee root = new Employee
            {
                Id = LastId,
                Name = $"root: {i}",
                EmailAddress = $"{i}@example.com",
                HireDate = DateTime.Now.AddYears(-i),
                DirectReports = new List<Employee>(), // prepare a collection for the child items, will be populated later in the code
            };
            data.Add(root);
            LastId++;

            for (int j = 1; j < 4; j++)
            {
                int currId = LastId;
                Employee firstLevelChild = new Employee
                {
                    Id = currId,
                    Name = $"first level child {j} of {i}",
                    EmailAddress = $"{currId}@example.com",
                    HireDate = DateTime.Now.AddDays(-currId),
                    DirectReports = new List<Employee>(), // collection for child nodes
                };
                root.DirectReports.Add(firstLevelChild); // populate the parent's collection
                LastId++;

                for (int k = 1; k < 3; k++)
                {
                    int nestedId = LastId;
                    // populate the parent's collection
                    firstLevelChild.DirectReports.Add(new Employee
                    {
                        Id = LastId,
                        Name = $"second level child {k} of {j} and {i}",
                        EmailAddress = $"{nestedId}@example.com",
                        HireDate = DateTime.Now.AddMinutes(-nestedId)
                    }); ;
                    LastId++;
                }
            }
        }

        return await Task.FromResult(data);
    }
}

Customization

The TreeList allows you to customize the default behavior of the Filter Row in a couple ways:

Configuring the Filter Menu

You can override the default Filter Row behavior for each column through the following property the TreeListColumn exposes:

Parameter Type and Default Value Description
DefaultFilterOperator FilterOperator Sets the default filter operator in the column it is declared for. Accepts a member of the FilterOperator enum. The selected operator must be applicable for the specific data type Check the supported options in the Filter Operators article. The provided default filter operator will be applied for both filters in the menu.
FilterOperators List<FilterListOperator> Specifies the available operators. Must contain only supported filter operators for the specific data type. If not defined, the component will use a default list of available operators based on the field type.

Configure the Filter Menu

@*Customize the Filter Menu*@

@using Telerik.DataSource

<TelerikTreeList Data="@Data"
                 IdField="Id"
                 ParentIdField="ParentId"
                 FilterMode="@TreeListFilterMode.FilterMenu"
                 Pageable="true" Width="850px" Height="400px">
    <TreeListColumns>
        <TreeListColumn DefaultFilterOperator="FilterOperator.StartsWith"
                        Field="Name" Expandable="true" Width="320px" />
        <TreeListColumn DefaultFilterOperator="FilterOperator.IsEqualTo"
                        Field="Id" Width="120px" />
        <TreeListColumn DefaultFilterOperator="FilterOperator.IsEqualTo"
                        Field="ParentId" Width="120px" />
        <TreeListColumn DefaultFilterOperator="FilterOperator.Contains"
                        Field="EmailAddress" Width="120px" />
        <TreeListColumn DefaultFilterOperator="FilterOperator.IsGreaterThanOrEqualTo"
                        Field="HireDate" Width="220px" />
    </TreeListColumns>
</TelerikTreeList>

@code {
    public List<Employee> Data { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Data = await GetTreeListData();
    }

    // sample model

    public class Employee
    {
        // denote the parent-child relationship between items
        public int Id { get; set; }
        public int? ParentId { get; set; }

        // custom data fields for display
        public string Name { get; set; }
        public string EmailAddress { get; set; }
        public DateTime HireDate { get; set; }
    }

    // data generation

    async Task<List<Employee>> GetTreeListData()
    {
        List<Employee> data = new List<Employee>();

        for (int i = 1; i < 15; i++)
        {
            data.Add(new Employee
                {
                    Id = i,
                    ParentId = null, // indicates a root-level item
                    Name = $"root: {i}",
                    EmailAddress = $"{i}@example.com",
                    HireDate = DateTime.Now.AddYears(-i)
                }); ;

            for (int j = 1; j < 4; j++)
            {
                int currId = i * 100 + j;
                data.Add(new Employee
                    {
                        Id = currId,
                        ParentId = i,
                        Name = $"first level child {j} of {i}",
                        EmailAddress = $"{currId}@example.com",
                        HireDate = DateTime.Now.AddDays(-currId)
                    });
            }
        }

        return await Task.FromResult(data);
    }
}

Filter Menu Template

The template will let you have full control over the Filter Row rendering and behavior. See how you can implement it and explore the example in the Filter Row Template article.

See Also

In this article