A fully-featured, headless data table library for Yew applications, inspired by TanStack Table v8. Provides compile-time type safety, a modular feature set, and a familiar hook-based API for building performant data-driven interfaces in Rust and WebAssembly.
yew-datatable separates the headless table engine (yew-datatable-core) from the Yew UI layer (yew-datatable), letting you use the engine standalone or with the provided Yew components and hooks.
- Headless Core — Pure logic, no UI assumptions; bring your own markup and styling
- Type-Safe Columns — Compile-time accessor guarantees with generic
ColumnDef<T> - Full Pipeline — Rows flow through filter → sort → group → expand → paginate automatically
- Hook-Based API —
use_tablehook mirrors the TanStackuseReactTablepattern - 100% Safe Rust — No
unsafeblocks, memory-safe by construction
| Category | Capabilities |
|---|---|
| Sorting | Single and multi-column, stable sort, custom comparators, natural ordering |
| Filtering | Column filters, global search, 16 built-in filter functions, custom functions |
| Pagination | Client-side and server-side modes, configurable page sizes, full navigation |
| Selection | Single-row, multi-row, select-all, toggle, row-click selection |
| Visibility | Show/hide columns, default visibility, bulk operations |
| Ordering | Reorder columns programmatically with move, swap, before/after |
| Pinning | Pin columns to left or right with automatic reordering |
| Sizing | Column widths with min/max constraints, resize lifecycle |
| Expansion | Expandable rows, tree data, auto-expand depth, expand-all |
| Grouping | Group by column values, multi-level grouping, aggregation display |
| Aggregation | Sum, mean, min, max, count, unique count, median, first, last |
[dependencies]
yew-datatable = "0.1"For the headless engine only:
[dependencies]
yew-datatable-core = "0.1"use yew::prelude::*;
use yew_datatable::prelude::*;
#[derive(Clone, PartialEq)]
struct Person { name: String, age: u32 }
#[function_component(MyTable)]
fn my_table() -> Html {
let columns = vec![
ColumnDefBuilder::new("name", "Name")
.accessor(|p: &Person| p.name.clone())
.build(),
ColumnDefBuilder::new("age", "Age")
.accessor(|p: &Person| p.age as i32)
.build(),
];
let data = vec![
Person { name: "Alice".into(), age: 30 },
Person { name: "Bob".into(), age: 25 },
];
let table = use_table(columns, data, None);
html! {
<div>
// Sortable headers — click to sort, shift-click for multi-sort
<table>
<thead><tr>
{table.visible_column_ids().iter().map(|id| {
let t = table.clone(); let id = id.clone();
html! { <th onclick={Callback::from(move |e: MouseEvent| {
t.toggle_sort(id.clone(), e.shift_key());
})}>{table.get_column_header(&id).unwrap_or_default()}</th> }
}).collect::<Html>()}
</tr></thead>
<tbody>
{table.visible_rows().iter().map(|row| html! {
<tr key={row.id.as_str().to_string()}>
{table.visible_column_ids().iter().map(|id| html! {
<td>{table.get_cell_value(&row.original, id).unwrap_or_default()}</td>
}).collect::<Html>()}
</tr>
}).collect::<Html>()}
</tbody>
</table>
// Pagination
<button disabled={!table.can_previous_page()}
onclick={let t=table.clone(); Callback::from(move |_| t.previous_page())}>
{"← Prev"}</button>
<span>{format!("Page {} / {}", table.current_page()+1, table.page_count())}</span>
<button disabled={!table.can_next_page()}
onclick={let t=table.clone(); Callback::from(move |_| t.next_page())}>
{"Next →"}</button>
</div>
}
}The library follows a two-crate design:
yew-datatable-core — The headless engine with zero UI dependencies. It provides the DataTable<T> coordinator, DataTableRowModel<T> pipeline, feature state types (SortingState, FilterState, PaginationState, etc.), and column definitions with type-safe accessors. Each feature lives in its own module under features/ with dedicated state, functions, and prelude re-exports.
yew-datatable — The Yew integration layer. It provides the use_table hook for reactive state management and pre-built components (DataTable, TableHeader, TableBody, Pagination) that wire into the core engine. All public types from both crates are available through yew_datatable::prelude::*.
| TanStack Concept | yew-datatable Equivalent |
|---|---|
useReactTable |
use_table hook |
ColumnDef |
ColumnDef<T> / ColumnDefBuilder |
accessorFn |
.accessor() builder method |
getCoreRowModel |
DataTableRowModel::process() |
getSortedRowModel |
Built into the pipeline |
getFilteredRowModel |
Built into the pipeline |
getPaginationRowModel |
Built into the pipeline |
flexRender |
Custom cell rendering via Callback<CellRenderContext<T>, Html> |
See the example/ directory for a full working demonstration with sorting, filtering, pagination, selection, column features, and a combined full-demo page.
cd example
trunk servecargo test --package yew-datatable-core --target x86_64-unknown-linux-gnuContributions are welcome. Please read CONTRIBUTING.md before submitting a pull request.
Distributed under the MIT license.
