Components / Data Table

Data Table

A full-featured table (sorting, a global filter, a column-visibility menu, row selection, and pagination) as one generic ZitsDataTable<TItem> over your own record type. It is built on the headless NaviusDataGrid<TItem> brain (a dependency-free, TanStack-Table-equivalent state engine), so the helm is pure markup and styling. The preview below is the real component running in WebAssembly.

Examples

Type in the filter to search by email, click a column header to cycle its sort (ascending → descending → off), toggle columns from the View menu, select rows with the checkboxes, and move through pages with Previous / Next. The Status and Amount columns each render through a CellTemplate.

success
ken99@example.com
$316.00
success
abe45@example.com
$242.00
processing
monserrat44@example.com
$837.00
success
silas22@example.com
$874.00
failed
carmella@example.com
$721.00
pending
jason78@example.com
$459.00
failed
rauls@example.com
$128.00
processing
lena.k@example.com
$603.00
success
noah.h@example.com
$512.00
pending
ava.m@example.com
$199.00
0 of 14 row(s) selected.
Page 1 of 2
razor
@using Navius.Primitives.Components.DataGrid

<ZitsDataTable TItem="Payment"
               Items="_payments"
               Columns="_columns"
               RowKey="@(p => p.Id)"
               FilterColumnKey="email" />

@code {
    private record Payment(string Id, string Status, string Email, decimal Amount);

    private readonly List<Payment> _payments = new()
    {
        new("m5gr84i9", "success",    "ken99@example.com",       316m),
        new("derv1ws0", "processing", "monserrat44@example.com", 837m),
        new("bhqecj4p", "failed",     "carmella@example.com",    721m),
        // ...more rows
    };

    private List<DataGridColumn<Payment>> _columns = new();

    protected override void OnInitialized() => _columns = new()
    {
        new() { Key = "status", Header = "Status", Accessor = p => p.Status, CellTemplate = StatusCell },
        new() { Key = "email",  Header = "Email",  Accessor = p => p.Email  },
        new() { Key = "amount", Header = "Amount", Accessor = p => p.Amount, CellTemplate = AmountCell },
    };

    // A CellTemplate is a RenderFragment<Payment>: render the cell however you like.
    private readonly RenderFragment<Payment> StatusCell = p =>
        @<ZitsBadge Variant="@StatusVariant(p.Status)" class="capitalize">@p.Status</ZitsBadge>;

    private readonly RenderFragment<Payment> AmountCell = p =>
        @<div class="text-right font-medium">@p.Amount.ToString("C")</div>;

    private static string StatusVariant(string status) => status switch
    {
        "success" => "default",
        "failed"  => "destructive",
        _          => "secondary",
    };
}

Anatomy

You feed ZitsDataTable a list of rows and a list of DataGridColumn<TItem> descriptors; it wraps the brain and renders the toolbar, the bordered table, and the pagination footer for you.

Anatomy text
ZitsDataTable<TItem>                      (wraps NaviusDataGrid<TItem>, the brain)
└── ZitsDataTableContent
    ├── toolbar
    │   ├── ZitsInput                     (global filter)
    │   └── ZitsDataTableViewOptions      ("View" column-visibility menu)
    ├── ZitsTable
    │   ├── selection checkbox column     (EnableSelection)
    │   └── ZitsDataTableColumnHeader     (per column; sortable ghost button)
    └── ZitsDataTablePagination           (EnablePagination: Prev / Next + selected count)

Installation

Pull the component (and its brain) into your project with the CLI.

Terminal bash
navius add data-table

API reference

ZitsDataTable<TItem>:

Prop Type Default
Items IEnumerable<TItem> -
Columns IReadOnlyList<DataGridColumn<TItem>> -
RowKey Func<TItem, object> the row itself
EnableSelection bool true
EnablePagination bool true
PageSize int 10
FilterColumnKey string? -
FilterPlaceholder string? "Filter..."

DataGridColumn<TItem>, one per column (from Navius.Primitives.Components.DataGrid):

Prop Type Default
Key string (required) -
Header string? Key
Accessor Func<TItem, object?>? -
CellTemplate RenderFragment<TItem>? Accessor value
Sortable bool true
EnableHiding bool true
FilterFn Func<TItem, string, bool>? -