Chapter 33 of 40

Remember the state: sorting, scroll position, open nodes

After a reload everything looks like before – one localStorage key per table, or your server.

  • ⏱ 4 min
  • ▶ Video episode 033
  • git tag ep-033
  • needs @guiexpert/table@1.1.89

After this chapter you can

  • switch on autoRestoreOptions
  • remember expanded tree nodes
  • choose a storage key
  • remember the column layout, checked and selected rows (since 1.1.92)
  • save the state on your server (since 1.1.92)

Switch it on

TableOptionsIf.autoRestoreOptions stores the state of a table in localStorage and restores it on the next start. Start from AutoRestoreOptions and switch on what you need:

src/model/order-table-options.ts
import { AutoRestoreOptions, TableOptions, type TableOptionsIf } from "@guiexpert/table";
import type { Order } from "./data/orders";
export function createOrderTableOptions(): TableOptionsIf {
return {
...new TableOptions(),
autoRestoreOptions: {
...new AutoRestoreOptions<Order>(),
getStorageKeyFn: () => "ge-demo-orders", // one key per table (localStorage)
autoRestoreSortingState: true,
autoRestoreScrollPosition: true,
autoRestoreColumnLayout: true // widths, order, hidden columns (since 1.1.92)
}
};
}
Live Sort, resize, reload
Screenshot: Sort, resize, reload Screenshot: Sort, resize, reload
Double-click “Total”, drag a column edge or a header, scroll down, then “reload page”. The table comes back exactly as you left it.

What can be remembered

OptionRemembers
autoRestoreSortingStatesorted columns and direction (incl. the header icon) – by property
autoRestoreScrollPositionscroll position (and the first visible row)
autoRestoreCollapsedExpandedStateexpanded / collapsed nodes of a tree – by getRowId
autoRestoreColumnLayoutwidth of resized columns, column order, hidden columns (1.1.92)
autoRestoreHeaderGroupStatecollapsed header groups (1.1.92)
autoRestoreCheckedStatechecked rows – by getRowId (1.1.92)
autoRestoreSelectedStateselected rows, columns or ranges (1.1.92)
autoRestoreCustomStateyour own data, e.g. a filter text: TableApi.setCustomState() (1.1.92)

Columns are stored by their property and rows by their id – never by position. A column the user moved is still the right column after a reload, and checked rows stay checked when the server sends them in another order.

For trees (chapter 30 (Tree table)) and checked or selected rows the table needs a stable id per row:

tree/tree.ts
autoRestoreOptions: {
...new AutoRestoreOptions<OrderNode>(),
getStorageKeyFn: () => "ge-demo-order-tree",
getRowId: node => node.id, // "Czechia", "Czechia/Becker KG", "4711"
autoRestoreCollapsedExpandedState: true,
autoRestoreScrollPosition: true
}

Your own storage – or your server

The same state is available as plain JSON: TableApi.getState() reads it, TableApi.applyState() applies it, TableOptionsIf.initialState starts with it and EventListenerIf.onStateChanged() reports every change – once, after the user stopped dragging or scrolling. That is all you need to keep the layout per user on your server:

src/table/order-table.ts
const listener = new EventAdapter();
listener.onStateChanged = (evt: GeStateChangeEvent) => {
ctx.info(`changed: ${evt.changedParts.join(", ")} – stored`); // or: fetch("/api/prefs", { method: "PUT", … })
};
start with the saved state
const saved = await (await fetch("/api/prefs/orders")).json(); // TableStateIf | null
const tableOptions: TableOptionsIf = { ...new TableOptions(), initialState: saved ?? undefined };

A “reset layout” button is one line – it also deletes the stored state:

ctx.button("reset layout", () => {
tableApi.resetState(); // layout of the code, stored state removed
});

sessionStorage instead of localStorage? Set storage: sessionStorage in the auto-restore options (or any object with getItem, setItem, removeItem). The state holds no cell values – but row ids can be personal data (an e-mail address as id); prefer technical ids.

Next

The finale of the course: a checklist for your own table – and when to choose something else. chapter 34 (Checklist & finale).

API used in this chapter