Veto
Components

Table

A templated table: you write the header cells and one row template, the table draws every row, the empty state, stripes and hover.

Basic

HeaderTemplate holds the header cells, RowTemplate one row's cells with the item as context, and FooterTemplate an optional totals row.

Recent orders
Order Customer Total
#1001 Ada Lovelace 42.50
#1002 Alan Turing 120.00
#1003 Grace Hopper 18.75
Total 181.25
razor
<Table TItem="Order" Items="_orders" Caption="Recent orders">
    <HeaderTemplate>
        <th>Order</th>
        <th>Customer</th>
        <th>Total</th>
    </HeaderTemplate>
    <RowTemplate>
        <td>@context.Number</td>
        <td>@context.Customer</td>
        <td>@context.Total.ToString("0.00")</td>
    </RowTemplate>
    <FooterTemplate>
        <td colspan="2">Total</td>
        <td>@_orders.Sum(o => o.Total).ToString("0.00")</td>
    </FooterTemplate>
</Table>

Empty state

With no items - or a null list - the body says so instead of collapsing to nothing. EmptyText for a sentence, EmptyContent for markup.

OrderCustomer
No data to show.
OrderCustomer
No orders yet. They show up here as they come in.
razor
<Table TItem="Order" Items="_orders" EmptyText="No orders yet." ... />

<Table TItem="Order" Items="_orders">
    ...
    <EmptyContent><strong>No orders yet.</strong> They show up here as they come in.</EmptyContent>
</Table>

Look

Striped, Bordered and Hover are on by default and can each be turned off. Dense tightens the cells.

OrderCustomerTotal
#1001Ada Lovelace42.50
#1002Alan Turing120.00
#1003Grace Hopper18.75
razor
<Table TItem="Order" Items="_orders"
       Striped="false" Bordered="false" Hover="false" Dense="true">
    ...
</Table>

Clickable rows, row classes and a sticky header

OnRowClick makes every row focusable and raises the item on click, Enter or Space. RowClass adds classes worked out from the item. StickyHeader keeps the header in view while the rows scroll inside RootMaxHeight.

OrderCustomerTotal
#2001Customer 111.50
#2002Customer 223.00
#2003Customer 334.50
#2004Customer 446.00
#2005Customer 557.50
#2006Customer 669.00
#2007Customer 780.50
#2008Customer 892.00
#2009Customer 9103.50
#2010Customer 10115.00
#2011Customer 11126.50
#2012Customer 12138.00
#2013Customer 13149.50
#2014Customer 14161.00
#2015Customer 15172.50
#2016Customer 16184.00
#2017Customer 17195.50
#2018Customer 18207.00
#2019Customer 19218.50
#2020Customer 20230.00
none
razor
<Table TItem="Order" Items="_orders"
       StickyHeader="true" RootMaxHeight="12rem"
       OnRowClick="o => _picked = o.Number"
       RowClass='o => o.Total > 100 ? "large-order" : null'
       ItemKey="o => o.Number">
    ...
</Table>

Parameters

Parameter Type Default Description
Items IEnumerable<TItem>? null The items, one row each. Null is shown as empty.
HeaderTemplate RenderFragment? null The header row's cells. No header without it.
RowTemplate RenderFragment<TItem> — One row's cells; the item is context.
FooterTemplate RenderFragment? null The footer row's cells. No footer without it.
EmptyText string "No data to show." What the body says with no items.
EmptyContent RenderFragment? null The empty state as markup, instead of EmptyText.
Caption string? null A caption naming the table.
Striped bool true Shade every other row.
Bordered bool true Border every cell; off leaves only the lines between rows.
Hover bool true Highlight the row under the pointer.
Dense bool false Tighter cell padding.
StickyHeader bool false Keep the header in view while rows scroll. Pair with RootMaxHeight.
OnRowClick EventCallback<TItem> — Raised on click, Enter or Space. Makes rows focusable.
RowClass Func<TItem, string?>? null Extra classes for a row, from its item.
ItemKey Func<TItem, object?>? null A unique key per item, so rows keep their DOM when re-ordered.
Something went wrong. Reload 🗙