Skip to content

Browser page state

GridView.PageState persists opaque JSON for one rendered GridViewSpec page in browser localStorage. It retains browser-local UI state across reloads for the same origin. It does not provide reactivity, UI behavior, domain drafts, or server persistence.

State sources

GridViewSpec provides two persistence mechanisms:

Mechanism Identity Use Authority
GridView.PageState spec.id + optional scope + namespace Browser-local persistent UI layout and renderer state Browser
GridPreference Authenticated user + grid_id Named presets and saved searches Host persistence backend

The URL is authoritative shareable request state, not a persistence mechanism. URL values win when present. GridView.PageState is not a server session. GridPreference is not a general page-state store.

Identity and scope

spec.id is the primary page-state identity. Set GridViewConfig.page_state_scope only when the same spec intentionally renders in separate browser contexts. The renderer emits the scope as data-cm-page-state-scope on the spec root.

from grid_view_spec.types import GridViewConfig, GridViewSpec

spec = GridViewSpec(
    id="catalogue",
    config=GridViewConfig(page_state_scope="workspace"),
    blocks=(...),
)

An empty page_state_scope is the default. Browser storage already isolates origins, so a scope does not encode a host name or origin.

Host setup

A rendered spec and the core GridViewSpec JavaScript bundle are sufficient. The package emits the root identity attributes. A host does not add a Django migration, HTTP route, GridViewHost method, or storage configuration for page state. Use page_state_scope only when a default spec.id identity needs intentional separation.

JavaScript API

Get a handle from the connected spec root or one of its descendants. UI mounted outside the spec root passes the root explicitly.

const root = document.getElementById("cm-spec-catalogue");
const state = GridView.PageState.forRoot(root);

if (state) {
  const drawer = state.get("layout.drawer");
  state.put("layout.drawer", { open: true, width: 480 });
  state.remove("layout.drawer");
}
Method Result
get(namespace) Stored JSON value or undefined
put(namespace, value) Replaces one namespace value
remove(namespace) Removes one namespace value

Values must be JSON-serializable. Malformed stored data reads as absent; a later valid put replaces it. Unavailable or full browser storage returns no value and does not persist writes. The handle does not observe changes or validate the host-owned value shape.

Namespaces

Use stable namespaces so independent capabilities do not overwrite each other.

Namespace Owner and contents
layout.drawer Host drawer layout snapshot
layout.filters Host filter-panel layout snapshot
layout.modal Host modal layout snapshot
grid.<block-id>.columns Shared table column layout
grid.<block-id>.ag_grid AG Grid renderer-specific state
host.<app>.* Host-owned opaque JSON

The package does not interpret host namespaces. Each renderer restores its own namespaces. When a namespace mirrors a URL value, the host gives the URL value precedence.

Table adapters use the literal block id in their namespace. The shared grid.<block-id>.columns value is an ordered array of { id, hidden, pinned?, width? }; it is independent of a table renderer. An AG Grid adapter keeps its filter, sort, flex-sizing, and other AG-only values in the adjacent grid.<block-id>.ag_grid namespace.

Storage boundary

GridView.PageState exposes browser-local get, put, and remove only. It does not expose a universal storage selector such as put(session, namespace, value): browser-local state and authenticated named preferences have different identity, authorization, lifecycle, and failure semantics. Hosts can use the same verbs in their own adapters without expanding the public GridViewSpec contract.

Upgrade compatibility

Existing GridPreference data and its host API remain unchanged. Renderer adapters migrate supported legacy browser grid keys once and clear obsolete keys, then write only the page-state namespaces. Named presets and saved searches remain untouched.

See Saved preferences for user-managed named views.