Filtering

Enable per-column filtering with a text input row below the headers. Filters run client-side by default, or are passed to your server callback in server-side mode.

Enabling Filters

Set Filterable="true" on the grid. A “Filter” toggle button appears in the toolbar. Click it to show or hide the filter row.

<ArcadiaDataGrid TItem="Employee" Data="@employees" Filterable="true">
    <ArcadiaColumn TItem="Employee" Title="Name" Field="@(e => e.Name)" />
    <ArcadiaColumn TItem="Employee" Title="Department" Field="@(e => e.Department)" />
    <ArcadiaColumn TItem="Employee" Title="Salary" Field="@(e => e.Salary)" Format="C0" />
</ArcadiaDataGrid>

When the filter row is visible, each column with a Field accessor gets a text input. Typing into the input filters the grid in real time.

Column-Level Control

Individual columns can opt out of filtering by setting Filterable="false". When Filterable is null (the default), the column is filterable if it has a Field accessor.

<ArcadiaDataGrid TItem="Employee" Data="@employees" Filterable="true">
    <ArcadiaColumn TItem="Employee" Title="Name" Field="@(e => e.Name)" />
    <ArcadiaColumn TItem="Employee" Title="Actions" Filterable="false">
        <Template Context="emp">
            <button @onclick="@(() => Edit(emp))">Edit</button>
        </Template>
    </ArcadiaColumn>
</ArcadiaDataGrid>

FilterDescriptor Type

Each active filter is represented by a FilterDescriptor:

public class FilterDescriptor
{
    public string Property { get; set; }        // Column key
    public FilterOperator Operator { get; set; } // Default: Contains
    public string Value { get; set; }            // User-entered text
}

Filter Operators

As of beta.10, the FilterOperator enum supports nine operators. The filter row UI now includes a dropdown next to each column’s input, allowing the user to pick the operator instead of always using Contains.

OperatorDescriptionExample
ContainsCell value contains the filter text (case-insensitive)“ali” matches “Alice”
EqualsCell value equals the filter text (case-insensitive)“alice” matches “Alice”
StartsWithCell value starts with the filter text”Al” matches “Alice”
EndsWithCell value ends with the filter text”ce” matches “Alice”
NotEqualsCell value does not equal the filter text (case-insensitive)“Bob” excludes “Bob”, shows all others
GreaterThanNumeric: cell value > filter value”80000” matches 95000
LessThanNumeric: cell value < filter value”80000” matches 72000
IsEmptyCell value is null, empty, or whitespace. No filter text requiredMatches rows where the cell is blank
IsNotEmptyCell value is not null, empty, or whitespace. No filter text requiredMatches rows where the cell has a value

The default operator is Contains. When IsEmpty or IsNotEmpty is selected, the text input is disabled since no value is needed.

Client-Side Behavior

In client-side mode (no LoadData), the grid applies filters internally using LINQ. Filters are:

  • Case-insensitive
  • Applied to the string representation of the cell value
  • Combined with AND logic (all filters must match)
  • Applied before sorting and paging

Filtering resets the page index to 0.

Server-Side Filtering

When LoadData is set, all active filters are passed in DataGridLoadArgs.Filters as an IReadOnlyList<FilterDescriptor>. The grid does not filter client-side — your callback handles filtering.

<ArcadiaDataGrid TItem="Employee" Data="@employees"
                 Filterable="true"
                 LoadData="@LoadEmployees"
                 ServerTotalCount="@totalCount">
    <ArcadiaColumn TItem="Employee" Title="Name" Field="@(e => e.Name)" />
    <ArcadiaColumn TItem="Employee" Title="Department" Field="@(e => e.Department)" />
</ArcadiaDataGrid>

@code {
    private List<Employee> employees = new();
    private int totalCount;

    private async Task LoadEmployees(DataGridLoadArgs args)
    {
        // args.Filters contains active FilterDescriptor entries
        var result = await EmployeeService.QueryAsync(
            skip: args.Skip,
            take: args.Take,
            filters: args.Filters);

        employees = result.Items;
        totalCount = result.TotalCount;
    }
}

Quick Filter

Beta.10 adds a cross-column quick filter. When ShowToolbar="true" is set, the toolbar includes a search input that filters all columns at once. The QuickFilter parameter provides two-way binding to the search text.

Typing into the quick filter searches across all columns with a Field accessor. A row is shown if any column’s value contains the search text (case-insensitive). The quick filter works alongside per-column filters — both must match for a row to appear.

<ArcadiaDataGrid TItem="Employee" Data="@employees"
                 ShowToolbar="true"
                 Filterable="true"
                 QuickFilter="@quickSearch"
                 QuickFilterChanged="@(val => quickSearch = val)">
    <ArcadiaColumn TItem="Employee" Title="Name" Field="@(e => e.Name)" />
    <ArcadiaColumn TItem="Employee" Title="Department" Field="@(e => e.Department)" />
    <ArcadiaColumn TItem="Employee" Title="Salary" Field="@(e => e.Salary)" Format="C0" />
</ArcadiaDataGrid>

<p>Searching for: @quickSearch</p>

@code {
    private string? quickSearch;

    private List<Employee> employees = new()
    {
        new("Alice", "Engineering", 95000),
        new("Bob", "Marketing", 72000),
        new("Carol", "Engineering", 105000),
    };

    record Employee(string Name, string Department, decimal Salary);
}

The quick filter text is included in DataGridLoadArgs.QuickFilter for server-side mode, so your LoadData callback can apply it server-side.

Note: Toggling the filter row visibility does not clear the filter values. Filters persist until the user clears the input text.