Skip to content

Saved views

Let users capture the table’s current state — search, sort, page, filters, column layout — under a name and re-apply it later. One prop mounts a ready-made menu; a headless hook backs custom UIs.

// Needs your kit's provider once at the root (e.g. <MantineProvider>).
import { DataTable } from "@adapttable/mantine"; // or mui, chakra, antd, unstyled
interface Person {
id: string;
name: string;
department: { name: string };
status: string;
salary: number;
}
const data: Person[] = [
{
id: "1",
name: "Amira Haddad",
department: { name: "Engineering" },
status: "active",
salary: 98000,
},
{
id: "2",
name: "Jonas Weber",
department: { name: "Design" },
status: "onleave",
salary: 76000,
},
{
id: "3",
name: "Priya Nair",
department: { name: "Engineering" },
status: "active",
salary: 112000,
},
{
id: "4",
name: "Sam Ortiz",
department: { name: "Sales" },
status: "left",
salary: 64000,
},
];
export function PeopleTable() {
return (
<DataTable
data={data}
rowKey={(r) => r.id}
columns={[
{ key: "name", sortable: true },
{
key: "department.name",
header: "Department",
filter: { type: "select", options: "auto" },
},
{ key: "status", filter: { type: "multiSelect", options: "auto" } },
{ key: "salary", filter: "numberRange", sortable: true },
]}
enableColumnMenu
savedViews={{ storageKey: "people-views" }}
/>
);
}
  • Setting savedViews renders the kit’s built-in Saved-views menu in the toolbar next to the Columns button: click a name to apply it, the trailing ✕ to delete it, or type a name and Save to capture the current state.
  • A view stores the table-scoped query string — search, sort, page and page-size, every f_* filter param, and the URL-persisted column layout. Only this table’s params are captured; saving under an existing name replaces it.
  • Applying first drops this table’s current params, then lays the view’s over — other tables sharing the URL are untouched, and anything the view doesn’t mention returns to its default.
  • The list persists as JSON under storageKey (localStorage by default).
  • adapter and urlKey default to the table’s own urlAdapter / urlKey, so usually only storageKey is needed.

savedViews takes UseSavedViewsOptions (the same options as the headless hook):

PropTypeDefaultDescription
storageKeystring— (required)Storage key for the view list, e.g. "people-table-views".
storageLayoutStoragelocalStorage (memory-only under SSR)Storage backend — supply your own to persist elsewhere.
adapterUrlStateAdapterthe table’s urlAdapterThe table’s URL-state backend.
urlKeystringthe table’s urlKeyThe table’s URL namespace — must match the table’s urlKey.
  • For custom UIs, use the headless hook and wire any menu into the toolbar slot (each adapter also exports its SavedViewsMenu component to pair with it):

    import { useSavedViews } from "@adapttable/core";
    const views = useSavedViews({ storageKey: "people-views", urlKey: "people" });
    // views.views, views.save("Active EU"), views.apply("Active EU"),
    // views.remove("Active EU")
  • Column layout is part of a view only when it lives in the URL (wire useColumnLayoutUrlState); the localStorage-backed layout from useColumnLayoutStorageState is not captured.

  • Views are local to the browser by default. Pass storage to persist them elsewhere; a full or denied storage degrades gracefully — the in-memory list keeps working for the session.

  • Multiple tables on one page: give each table its own urlKey (so params are namespaced, left.q, left.f_status, …) and a distinct storageKey. Each menu captures and applies only its own namespace.

  • A view stores state, not rows — applying one re-runs the usual search/filter/sort pipeline (or re-fires onQueryChange on the server tier).

  • The menu’s savedViews / saveView / viewName / deleteView labels are overridable via labels and localized by the @adapttable/i18n presets.

See it live in the demo.