New to Telerik UI for BlazorStart a free 30-day trial

Search Grid on Button Click

Updated on Mar 26, 2026

Environment

ProductGrid for Blazor

Description

I am using the Grid SearchBox, but I don't want it to search for every typed letter. I would like a button next to the search textbox set the search filter after the button is clicked.

Solution

  1. Bind the Grid with an OnRead event handler.
  2. Replace the GridSearchBox with a TextBox and a Button with an OnClick event handler.
  3. In the click/change handler, build a CompositeFilterDescriptor with a LogicalOperator of Or. Populate its FilterDescriptors collection with filters for all searchable Grid model fields.
  4. Add the composite filter descriptor to the Grid State to search programmatically.
  5. (optional) Handle the TextBox OnChange event too. This will allow searching on textbox blur and Enter keypress.
  6. (optional) Wrap the search textbox in a <div class="k-toolbar-item"> to enable the built-in Grid ToolBar keyboard navigation and achieve the same behavior as with the Telerik GridSearchBox.
  7. (optional) Handle the @onkeyup event of the textbox wrapper div to clear the search value, similar to the Telerik GridSearchBox.

Note the difference between searching and filtering in the Grid state. Filtering affects the Grid's filtering UI (row or menu), while searching does not.

Also see the Filter Descriptors documentation, which explains the differences between FilterDescriptor and CompositeFilterDescriptor.

Search Grid Programmatically on Button Click

@using Telerik.DataSource
@using Telerik.DataSource.Extensions

<TelerikGrid TItem="@GridItem"
             OnRead="@OnGridRead"
             Pageable="true"
             PageSize="5"
             @ref="@GridRef">
    <GridToolBarTemplate>
        <div class="k-toolbar-item" @onkeyup="@OnTextBoxKeyUp">
            <TelerikTextBox @bind-Value="@SearchValue"
                            Class="k-searchbox"
                            OnChange="@SearchGrid"
                            Width="180px">
                <TextBoxPrefixTemplate>
                    <TelerikSvgIcon Icon="@SvgIcon.Search" />
                </TextBoxPrefixTemplate>
            </TelerikTextBox>
        </div>
        <TelerikButton OnClick="@SearchGrid" Icon="@SvgIcon.Search">Search Grid</TelerikButton>
        <TelerikButton OnClick="@ClearSearch" Icon="@SvgIcon.Cancel">Clear Search</TelerikButton>
    </GridToolBarTemplate>
    <GridColumns>
        <GridColumn Field="@nameof(GridItem.Name1)" />
        <GridColumn Field="@nameof(GridItem.Name2)" />
    </GridColumns>
</TelerikGrid>

@code {
    private List<GridItem> GridData { get; set; } = new List<GridItem>();
    private TelerikGrid<GridItem>? GridRef;

    private string SearchValue { get; set; } = string.Empty;

    private async Task SearchGrid()
    {
        if (SearchValue == string.Empty)
        {
            await ClearSearch();
            return;
        }

        GridState<GridItem> state = GridRef!.GetState();

        CompositeFilterDescriptor? oldCfd = state.SearchFilter as CompositeFilterDescriptor;
        if (oldCfd is not null)
        {
            FilterDescriptor? oldFd = oldCfd.FilterDescriptors.FirstOrDefault() as FilterDescriptor;
            if (oldFd?.Value?.ToString() == SearchValue)
            {
                // Avoid duplicate data requests for the same search value.
                return;
            }
        }

        CompositeFilterDescriptor cfd = new()
        {
            LogicalOperator = FilterCompositionLogicalOperator.Or,
            FilterDescriptors = new FilterDescriptorCollection()
        };

        // Add one FilterDescriptor for each string column to search in.

        cfd.FilterDescriptors.Add(new FilterDescriptor()
        {
            Member = nameof(GridItem.Name1),
            Value = SearchValue,
            Operator = FilterOperator.Contains
        });

        cfd.FilterDescriptors.Add(new FilterDescriptor()
        {
            Member = nameof(GridItem.Name2),
            Value = SearchValue,
            Operator = FilterOperator.Contains
        });

        state.SearchFilter = cfd;

        await GridRef.SetStateAsync(state);
    }

    private async Task ClearSearch()
    {
        SearchValue = string.Empty;

        GridState<GridItem> state = GridRef!.GetState();

        if (state.SearchFilter is not null)
        {
            state.SearchFilter = null;
            await GridRef.SetStateAsync(state);
        }
    }

    private void OnTextBoxKeyUp(KeyboardEventArgs args)
    {
        // Simulate GridSearchBox behavior - clear the textbox on Escape key press.
        if (args.Key == "Escape")
        {
            SearchValue = string.Empty;
        }
    }

    private async Task OnGridRead(GridReadEventArgs args)
    {
        DataSourceResult result = await GridData.ToDataSourceResultAsync(args.Request);
        args.Data = result.Data;
        args.Total = result.Total;
    }

    protected override Task OnInitializedAsync()
    {
        for (int j = 1; j <= 25; j++)
        {
            GridData.Add(new GridItem() {
                ID = j,
                Name1 = "Name " + (char)(j + 64) + (char)(j + 64),
                Name2 = "Name " + (char)(j + 65) + (char)(j + 65)
            });
        }

        return base.OnInitializedAsync();
    }

    public class GridItem
    {
        public int ID { get; set; }
        public string Name1 { get; set; } = string.Empty;
        public string Name2 { get; set; } = string.Empty;
    }
}

See Also