Data Table
A powerful and flexible data table component with sorting, filtering, pagination, and row selection.
Basic Table
A simple table with automatic sorting and pagination. Toggle the style options below to explore layout variants.
ID | Name | Email | Age |
|---|---|---|---|
| 1 | Paul Kelly | laura.martin@enterprise.net | 50 |
| 2 | Sharon Parker | jimmy.thomas@business.org | 32 |
| 3 | Edward Reyes | michael.stewart@enterprise.net | 50 |
| 4 | Linda Carter | patricia.lee908@example.com | 24 |
| 5 | Steven Gutierrez | christine.ramirez252@company.com | 23 |
Row Selection
Table with multiple row selection using checkboxes.
Name | Email | Role | |
|---|---|---|---|
| Paul Kelly | laura.martin@enterprise.net | Developer | |
| Sharon Parker | jimmy.thomas@business.org | Moderator | |
| Edward Reyes | michael.stewart@enterprise.net | Analyst | |
| Linda Carter | patricia.lee908@example.com | Admin | |
| Steven Gutierrez | christine.ramirez252@company.com | Moderator |
Use arrow keys to navigate rows, and Enter/Space to toggle selection. Enable keyboard navigation via the checkbox above.
Custom Cell Templates
Use custom templates to render cells with badges, buttons, and other components.
Name | Status | Role | Actions |
|---|---|---|---|
| Paul Kelly | Pending | Developer | |
| Sharon Parker | Suspended | Moderator | |
| Edward Reyes | Inactive | Analyst | |
| Linda Carter | Pending | Admin | |
| Steven Gutierrez | Suspended | Moderator |
Server-Side Data
Use the ServerData callback to load, sort, filter and paginate data on the server. The component passes a DataTableRequest with the current page, page size, sort column and search text. Returns DataTableResult
ID | Customer | Product | Status | Amount |
|---|---|---|---|---|
| 1 | Customer 1 | Gadget Lite | Shipped | 134.33 |
| 2 | Customer 2 | Device Max | Delivered | 395.55 |
| 3 | Customer 3 | Widget Pro | Cancelled | 156.76 |
| 4 | Customer 4 | Gadget Lite | Pending | 417.97 |
| 5 | Customer 5 | Device Max | Shipped | 179.18 |
| 6 | Customer 6 | Widget Pro | Delivered | 440.40 |
| 7 | Customer 7 | Gadget Lite | Cancelled | 201.61 |
| 8 | Customer 8 | Device Max | Pending | 462.82 |
| 9 | Customer 9 | Widget Pro | Shipped | 224.04 |
| 10 | Customer 10 | Gadget Lite | Delivered | 485.25 |
Infinite Scroll (Server-Side)
Set ItemsProvider to a DataTableVirtualProvider delegate. The component renders rows via Virtualize so only visible rows are in the DOM. The delegate receives StartIndex, Count, SortDescriptors, and SearchText — no page/pageSize math needed. Sorting and search trigger a virtualizer refresh automatically.
ID | Customer | Product | Status | Amount |
|---|
Virtualize (Client-Side)
Set Virtualize=true to keep all data in memory but only render visible DOM rows. Search and sort still run client-side. Useful for large in-memory datasets (500–20k rows) where you don't want pagination.
ID | Customer | Product | Status | Amount |
|---|
Column Pinning
Pin columns to the left or right edge so they stay visible while scrolling horizontally. Add Pinned="ColumnPinnedSide.Left" or Pinned="ColumnPinnedSide.Right" to any column. Set an explicit Width on pinned columns so offsets can be calculated correctly.
Name | Department | Title | Location | Manager | Start Date | Salary | Status | Actions |
|---|---|---|---|---|---|---|---|---|
Alice Johnson alice@acme.com | Engineering | Senior Engineer | New York | Carol White | Jan 2022 | $145,000 | Active | |
Bob Smith bob@acme.com | Design | UI/UX Designer | San Francisco | Carol White | Mar 2022 | $120,000 | Active | |
Carol White carol@acme.com | Engineering | Engineering Manager | New York | Henry Brown | Jun 2019 | $180,000 | Active | |
David Kim david@acme.com | Product | Product Manager | Austin | Henry Brown | Sep 2021 | $155,000 | Active | |
Eva Martinez eva@acme.com | Sales | Account Executive | Chicago | Frank Lee | Feb 2023 | $95,000 | Active |
Self Referencing Rows (Chart of Accounts)
Set ChildrenProperty to render a self-referencing hierarchy in-place. Rows expand and collapse with chevrons. When searching, ancestor rows containing matching descendants are automatically expanded. Combined here with column pinning to keep Account Name visible while scrolling across all the accounting columns.
Account Name | Code | Type | Description | Currency | Balance | Status | Actions |
|---|---|---|---|---|---|---|---|
| 1000 | Asset | All asset accounts | |||||
| 2000 | Liability | All liability accounts | |||||
| 3000 | Equity | Owner's equity and retained earnings | |||||
| 4000 | Revenue | All revenue and income accounts | |||||
| 5000 | Expense | All operating and non-operating expense accounts |
Column Resizing & Reordering
Enable Resizable to add drag handles on column headers for width adjustment. Enable Reorderable to let users drag columns into a new order — columns shift smoothly into place as you drag. Both work independently or together. Per-column Resizable/Reorderable overrides the table-level default.
Name | Department | Title | Location | Salary | Status |
|---|---|---|---|---|---|
| Alice Johnson | Engineering | Senior Engineer | New York | $145,000 | Active |
| Bob Smith | Design | UI/UX Designer | San Francisco | $120,000 | Active |
| Carol White | Engineering | Engineering Manager | New York | $180,000 | Active |
| David Kim | Product | Product Manager | Austin | $155,000 | Active |
| Eva Martinez | Sales | Account Executive | Chicago | $95,000 | Active |
Row Context Menu
Right-click any row to open a context menu scoped to that row. The RowContextMenu render fragment receives a DataTableRowMenuContext with the row's item, current selection, and visible column IDs. Use any ContextMenuItem, ContextMenuSeparator, or sub-menu components inside it.
Name | Department | Title | Salary | Status |
|---|---|---|---|---|
| Alice Johnson | Engineering | Senior Engineer | $145,000 | Active |
| Bob Smith | Design | UI/UX Designer | $120,000 | Active |
| Carol White | Engineering | Engineering Manager | $180,000 | Active |
| David Kim | Product | Product Manager | $155,000 | Active |
| Eva Martinez | Sales | Account Executive | $95,000 | Active |
Sortable Row Reorder
Use AdditionalRowAttributes to attach data-sortable-id to each table row. Wrap the DataTable in a Sortable root and SortableContent, then add a drag handle column via CellTemplate.
Task | Assignee | Status | |
|---|---|---|---|
| Design wireframes | Alice | Done | |
| Write unit tests | Bob | In Progress | |
| Implement API | Carol | To Do | |
| Code review | David | In Progress | |
| Deploy to staging | Eva | To Do |
Global Search & Column Visibility
Search across all columns and toggle column visibility.
ID | Name | Email | Age | Role | Status |
|---|---|---|---|---|---|
| 1 | Paul Kelly | laura.martin@enterprise.net | 50 | Developer | Pending |
| 2 | Sharon Parker | jimmy.thomas@business.org | 32 | Moderator | Suspended |
| 3 | Edward Reyes | michael.stewart@enterprise.net | 50 | Analyst | Inactive |
| 4 | Linda Carter | patricia.lee908@example.com | 24 | Admin | Pending |
| 5 | Steven Gutierrez | christine.ramirez252@company.com | 23 | Moderator | Suspended |
| 6 | Scott Flores | jimmy.white@enterprise.net | 32 | Guest | Pending |
| 7 | Donna Morales | melissa.sanchez@business.org | 35 | Admin | Active |
| 8 | John Stewart | jason.brooks@company.com | 52 | Developer | Inactive |
| 9 | Emily Morgan | michael.miller@organization.com | 32 | Manager | Active |
| 10 | Melissa Wilson | christopher.wright779@company.com | 35 | Designer | Inactive |
Empty State
Displays a message when there's no data to show.
No results found
Loading State
Shows a loading indicator while data is being fetched.
Name | Email | Role |
|---|---|---|
| Paul Kelly | laura.martin@enterprise.net | Developer |
| Sharon Parker | jimmy.thomas@business.org | Moderator |
| Edward Reyes | michael.stewart@enterprise.net | Analyst |
| Linda Carter | patricia.lee908@example.com | Admin |
| Steven Gutierrez | christine.ramirez252@company.com | Moderator |
Without Toolbar
A minimal table without the toolbar (no search or column visibility).
Name | Email | Age |
|---|---|---|
| Paul Kelly | laura.martin@enterprise.net | 50 |
| Sharon Parker | jimmy.thomas@business.org | 32 |
| Edward Reyes | michael.stewart@enterprise.net | 50 |
| Linda Carter | patricia.lee908@example.com | 24 |
| Steven Gutierrez | christine.ramirez252@company.com | 23 |
Custom Toolbar Actions
Add custom action buttons to the toolbar.
Name | Email | Role |
|---|---|---|
| Paul Kelly | laura.martin@enterprise.net | Developer |
| Sharon Parker | jimmy.thomas@business.org | Moderator |
| Edward Reyes | michael.stewart@enterprise.net | Analyst |
| Linda Carter | patricia.lee908@example.com | Admin |
| Steven Gutierrez | christine.ramirez252@company.com | Moderator |
Accessibility Features
Built-in accessibility features following WAI-ARIA design patterns.
ARIA Attributes
- ✓
role="grid"for screen readers - ✓
aria-sortindicates column sort direction - ✓
aria-selectedindicates row selection state - ✓
aria-labelon checkboxes for selection - ✓ Focusable rows with visible focus indicator
Keyboard Shortcuts
Navigate and interact with the table using keyboard.
DataTable API
DataTable component parameters and their types.
| Prop | Type | Default | Description |
|---|---|---|---|
| Data | IEnumerable<TData> | — | Required. The data source for the table. |
| Columns | RenderFragment? | null | Slot for DataTableColumn child components. |
| SelectionMode | DataTableSelectionMode | None | Row selection mode: None, Single, Multiple. |
| SelectedItems | IReadOnlyCollection<TData> | [ ] | Currently selected items. Use @bind-SelectedItems for two-way binding. |
| EnableKeyboardNavigation | bool | true | Arrow key navigation and Enter/Space row selection. |
| ShowToolbar | bool | true | Whether to show the toolbar (search + column visibility). |
| ShowPagination | bool | true | Whether to show pagination controls. |
| ColumnsVisibility | bool | true | Whether to show the column visibility toggle button in the toolbar. |
| IsLoading | bool | false | Shows a loading indicator instead of table content. |
| InitialPageSize | int | 5 | The initial number of rows per page. |
| PageSizes | int[] | [5,10,20,50,100] | Available page size options in the pagination selector. |
| Dense | bool | true | Compact cell padding (header h-9, body py-2 px-4). When false, uses h-12 / p-4. |
| HeaderBackground | bool | true | Applies bg-muted/50 to the header row. |
| HeaderBorder | bool | false | Vertical dividers between header cells (divide-x divide-border). |
| CellBorder | bool | false | Vertical dividers between body cells (divide-x divide-border). |
| HeaderClass | string? | null | Extra CSS classes on the <thead> element. |
| HeaderRowClass | string? | null | Extra CSS classes on the header <tr>. |
| BodyRowClass | string? | null | Extra CSS classes on each body <tr>. |
| ToolbarActions | RenderFragment? | null | Custom action buttons rendered inside the toolbar. |
| EmptyTemplate | RenderFragment? | null | Custom content shown when the table has no rows. |
| LoadingTemplate | RenderFragment? | null | Custom content shown when IsLoading is true. |
| AriaLabel | string? | null | ARIA label applied to the <table> element. |
| Class | string? | null | Extra CSS classes on the outer container div. |
| ServerData | Func<DataTableRequest, Task<DataTableResult<TData>>>? | null | Server-side paged data callback. Request carries Page, PageSize, SortDescriptors, and SearchText. |
| ItemsProvider | DataTableVirtualProvider<TData>? | null | Server-side virtualised provider for infinite scroll. Request carries StartIndex, Count, SortDescriptors, SearchText, and CancellationToken. Overrides Data and ServerData when set. |
| Virtualize | bool | false | Client-side DOM-windowing via Virtualize. All rows stay in memory; only visible nodes are rendered. Pagination is hidden. |
| ItemHeight | float | 40 | Row height in px passed to the virtualizer as ItemSize. Must match your actual row height when Virtualize=true or ItemsProvider is set. |
| Height | string | "400px" | CSS height of the scroll container. Required when Virtualize=true or ItemsProvider is set. |
| VirtualizeOverscanCount | int | 3 | Extra rows rendered beyond the viewport to reduce blank flicker during fast scrolling. |
| OnSort | EventCallback<(string, SortDirection)> | — | Fires when the user changes the sort column or direction. |
| OnFilter | EventCallback<string?> | — | Fires when the global search value changes. |
| PreprocessData | Func<IEnumerable<TData>, Task<IEnumerable<TData>>>? | null | Async hook to transform data before filtering and sorting. |
| ChildrenProperty | Func<TData, IEnumerable<TData>?>? | null | Returns child items for each row, activating tree mode. Children render inline with depth indentation. Incompatible with ItemsProvider (virtualised server mode). |
| LoadChildrenAsync | Func<TData, Task<IEnumerable<TData>>>? | null | Lazy async child loader — called on first expand of a node. Activates tree mode. Use with HasChildrenField to control whether the expander is shown before loading. |
| HasChildrenField | Func<TData, bool>? | null | Hints whether a node has children without loading them. In lazy mode, the expander is shown for all nodes unless this is provided. |
| ValueField | Func<TData, string>? | null | Returns a stable unique key per item for tracking expanded state. Strongly recommended in tree mode; falls back to RuntimeHelpers.GetHashCode when omitted. |
| ExpandedValues | HashSet<string>? | null | Two-way bindable set of expanded row keys. Use @bind-ExpandedValues to persist or restore the expand state across renders. |
| Resizable | bool | false | Adds drag handles on column headers so users can adjust widths at runtime. Activates table-layout:fixed automatically. Per-column Resizable on DataTableColumn overrides this. |
| MinColumnWidth | int | 80 | Minimum column width in pixels enforced during drag-to-resize. |
| SyncWidthOnResize | bool | false | When true, the table's total width is updated to match the sum of all column widths during and after resize. Pair with TableContainerClass="border-0" for the best visual result. |
| Striped | bool | false | Enables alternating row background (zebra striping). |
| StripeClass | string? | odd:bg-muted/30 | Tailwind class for the stripe. Override to change colour or swap odd/even, e.g. even:bg-muted/30. |
| OnColumnResize | EventCallback<(string, string)> | — | Fires when the user finishes resizing a column. Provides (ColumnId, NewCssWidth). |
| Reorderable | bool | false | Lets users drag column headers to reorder them. Columns animate into place as you drag. Pinned and selection columns are excluded. Per-column Reorderable overrides this. |
| OnColumnReorder | EventCallback<(string, int)> | — | Fires when the user drops a column into a new position. Provides (ColumnId, NewIndex). |
| RowContextMenu | RenderFragment<DataTableRowMenuContext<TData>>? | null | Template for the context menu shown on row right-click. Receives DataTableRowMenuContext with Item, SelectedItems, and VisibleColumns. |
| AdditionalRowAttributes | Func<TData, Dictionary<string, object>?>? | null | Callback supplying extra HTML attributes per body <tr>. E.g. supply data-sortable-id for Sortable row reorder, or arbitrary data-* / aria-* attributes. |
DataTableColumn API
DataTableColumn parameters and their types.
| Prop | Type | Default | Description |
|---|---|---|---|
| Property | Func<TData, TValue> | — | Required. Expression that returns the column value from a row. |
| Header | string | — | Required. Column header label text. |
| Id | string? | null | Unique column ID. Auto-generated from Header when omitted. |
| Sortable | bool | false | Whether clicking the header sorts by this column. |
| Filterable | bool | false | Whether this column is searched by the global search filter. |
| Alignment | ColumnAlignment | Left | Cell alignment: Left, Center, Right. |
| CellTemplate | RenderFragment<TData>? | null | Custom cell render template. Receives the row item as context. |
| Visible | bool | true | Whether the column is shown. Can be toggled via the column visibility menu. |
| Width | string? | null | Fixed column width (e.g. "200px", "20%"). |
| MinWidth | string? | null | Minimum column width CSS value. |
| MaxWidth | string? | null | Maximum column width CSS value. |
| CellClass | string? | null | Extra CSS classes on every body cell in this column. |
| HeaderClass | string? | null | Extra CSS classes on this column's header cell. |
| Pinned | ColumnPinnedSide | None | Sticks the column to the Left or Right edge during horizontal scroll. A shadow separator marks the boundary. Requires an explicit px Width for reliable offset calculation. |
| Resizable | bool? | null | Per-column resize override. null inherits the table-level Resizable setting. |
| Reorderable | bool? | null | Per-column reorder override. null inherits the table-level Reorderable setting. Pinned columns and the selection column are always excluded. |