Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

Filtering

A filter in each column's header, lists of values, operators, and filters in the address.

Static server-side rendering: no circuit, no WebAssembly.

Column filters

Use Filterable on a column for a filter in its header. Text matches anywhere, a date its day, enums and booleans get a list of checkboxes, and a number takes a range: at least, at most, or both.

Preview

Filtered orders
Order
Customer
Status
Total
1023Katherine JohnsonPending$64.75
1022Margaret HamiltonRefunded$483.00
1021Ada LovelaceFailed$441.25
1020Alan TuringPaid$399.50
1019Linus TorvaldsPending$357.75
No filters

Code

Filters.razor
@* Column filters: a funnel in each Filterable header opens the filter, and is marked while it's
   in use. FilterPanel lists them all below the rows. Text matches anywhere, enums get a list of checkboxes, numbers take a range. *@
<Table Items="Orders.All" PageSize="5" InitialSort="-number" Caption="Filtered orders" QueryPrefix="orders-" FilterPanel Grow>
    <PropertyColumn Property="o => o.Number" Title="Order" Align="CellAlign.Start" Sortable />
    <PropertyColumn Property="o => o.Customer" Sortable Filterable />
    <PropertyColumn Property="o => o.Status" Sortable Filterable />
    <PropertyColumn Property="o => o.Total" Format="C" Sortable Filterable />
</Table>

Static: Filters apply as you type.

The funnel is marked while its column is filtered, and Clear in its panel removes that filter. Use FilterPanel for a row below the table that lists every filter, with Clear for all of them; it's always there, so filtering doesn't move anything.

Lists of values

An enum or bool column's filter is a list of checkboxes. Every box ticked is no filter, and none ticked shows no rows.

Preview

Support tickets
Subject
Team
Priority
Open
Refund not receivedBillingHighTrue
New logo filesDesignLowFalse
Export times outEngineeringHighTrue
Invoice has the wrong addressFinanceMediumTrue
Terms of service questionLegalFalse

Code

FilterLists.razor
@* An enum or bool column's filter is a list: all ticked is no filter, and none ticked shows no rows.
   A nullable column gets a (Blank) row, and a list of more than ten gets a search. *@
<Table Items="_tickets" PageSize="5" Caption="Support tickets" QueryPrefix="lists-" Grow>
    <PropertyColumn Property="t => t.Subject" />
    <PropertyColumn Property="t => t.Team" Sortable Filterable />
    <PropertyColumn Property="t => t.Priority" Sortable Filterable />
    <PropertyColumn Property="t => t.Open" Filterable />
</Table>

@code {
    private enum Team { Billing, Design, Engineering, Finance, Legal, Marketing, Operations, Product, Research, Sales, Security, Support }

    private enum Priority { High, Medium, Low }

    private sealed record Ticket(string Subject, Team Team, Priority? Priority, bool Open);

    private static readonly Ticket[] _tickets =
    [
        new("Refund not received", Team.Billing, Priority.High, true),
        new("New logo files", Team.Design, Priority.Low, false),
        new("Export times out", Team.Engineering, Priority.High, true),
        new("Invoice has the wrong address", Team.Finance, Priority.Medium, true),
        new("Terms of service question", Team.Legal, null, false),
        new("Newsletter bounced", Team.Marketing, Priority.Low, true),
        new("Server moved", Team.Operations, null, false),
        new("Dark mode request", Team.Product, Priority.Low, true),
        new("Survey results", Team.Research, Priority.Medium, false),
        new("Quote for fifty seats", Team.Sales, Priority.High, true),
        new("Password reset fails", Team.Security, Priority.High, true),
        new("Can't sign in", Team.Support, Priority.Medium, true),
    ];
}

Static: Ticks apply after a short pause.

A text column can list its values too. FilterList reads them from Items, and FilterValues finds them yourself, as from a database, with FilterValuesRequest.ToResultAsync doing the work. Each list shows what the other filters leave, and keeps what's ticked listed so it can be unticked.

Preview

Orders by customer
Order
Customer
City
Region
1001Customer 001City 01West
1002Customer 002City 02East
1003Customer 003City 03West
1004Customer 004City 04East
1005Customer 005City 05West

Code

FilterValues.razor
@* FilterList reads a text column's values from Items. FilterValues finds them yourself, as from a
   database: it gets what's typed in the list's box and what the other filters leave. *@
<Table Items="_orders" PageSize="5" Caption="Orders by customer" QueryPrefix="values-" Grow>
    <PropertyColumn Property="o => o.Number" Title="Order" />
    <PropertyColumn Property="o => o.Customer" Sortable Filterable FilterValues="LoadCustomers" />
    <PropertyColumn Property="o => o.City" Sortable Filterable FilterList />
    <PropertyColumn Property="o => o.Region" Filterable />
</Table>

@code {
    private enum Region { East, West }

    private sealed record Order(int Number, string Customer, string? City, Region Region);

    private static readonly Order[] _orders = Enumerable.Range(1, 600)
        .Select(i => new Order(1000 + i, $"Customer {i:000}", i % 25 == 0 ? null : $"City {i % 12:00}", i % 2 == 0 ? Region.East : Region.West))
        .ToArray();

    private static readonly IReadOnlyList<DataField<Order>> _fields = DataFields.Of<Order>();

    // With a database, r.ToResultAsync(db.Orders, _fields, (q, ct) => q.ToListAsync(ct)).
    private static ValueTask<FilterValuesResult> LoadCustomers(FilterValuesRequest r) =>
        ValueTask.FromResult(r.ToResult(_orders.AsQueryable(), _fields));
}

Static: The script asks this page's own address for the values, with one more key, and takes the list from the response.

Filters in the address

Filters go in the URL as ?f-customer=ada (in the Column filters example, ?orders-f-customer=ada: that table has a QueryPrefix, so it sorts and pages apart from the others on the page, as under Several tables on a page). A number's two ends go in as ?f-total=100&f-total-to=500, so the form needs no script. For filters of your own, use a FilterForm above the table.

Choosing an operator

Use FilterOperators to choose an operator in a column's filter, as a DataGrid's columns do by default, or to limit the ones it offers. The first is the default, and a condition with any other matches nothing, even in an address written by hand. It goes in the address when it isn't the default, with its value: ?f-total-op=between&f-total=100&f-total-to=500.

Preview

Orders by operator
Order
Customer
Status
Total
1023Katherine JohnsonPending$64.75
1022Margaret HamiltonRefunded$483.00
1021Ada LovelaceFailed$441.25
1020Alan TuringPaid$399.50
1019Linus TorvaldsPending$357.75

Code

FilterOperators.razor
@* FilterOperators puts an operator above a column's value; the first is the default. Without it, a
   Table's column keeps its simple field, as Status does. *@
<Table Items="Orders.All" PageSize="5" InitialSort="-number" Caption="Orders by operator" QueryPrefix="ops-" Grow>
    <PropertyColumn Property="o => o.Number" Title="Order" Align="CellAlign.Start" Sortable />
    <PropertyColumn Property="o => o.Customer" Sortable Filterable
                    FilterOperators="[FilterOperator.Contains, FilterOperator.StartsWith, FilterOperator.Equals]" />
    <PropertyColumn Property="o => o.Status" Sortable Filterable />
    <PropertyColumn Property="o => o.Total" Format="C" Sortable Filterable
                    FilterOperators="[FilterOperator.GreaterThanOrEqual, FilterOperator.LessThanOrEqual, FilterOperator.Between]" />
</Table>

Filters in code

The filter is a Filter: Filter.All of one condition per filtered column (contains for text, between for a number, equals for a date, in for a choice, whose Values are what's ticked, with null for the blank row and none for nothing ticked). Set one in C# with @bind-Filter to filter from code, on an interactive page. A condition no column's panel can show, such as an or, still applies, and shows as a tag that removes it:

razor
<Table Items="orders" @bind-Filter="filter">...</Table>

@code {
    Filter? filter = Filter.Where("status", FilterOperator.Equals, "Paid");
}

Data and filters has the operators and the filter syntax, and Loading data how a column's condition reaches the database.

Connection lost

Rejoining the server…