Skip to content

Server / lazy (Mode B)

By default the engine computes the whole aggregated tree once and ships it, so every expand/collapse is client-side with zero round-trips (Mode A — see virtualization). When the tree is too large to ship at once, switch to lazy Mode B: the grid starts at the root level and fetches a node’s children only when you expand it. The engine still does all the math — each expand re-materialises just that node’s children — and results are cached by stable node id, so a re-expand is instant with zero network.

from dash import Input, Output, callback
from dash_tensor_grid import TensorGrid
from dash_tensor_grid.engine import GridDataEngine
engine = GridDataEngine(sales) # a source too large to ship as one tree
dims = ["region", "country", "city"]
agg = {"revenue": "sum", "cost": "sum"}
# Mode B: ship NO tree up front — only the column defs. `data_mode="lazy"`.
grid = TensorGrid(
id="grid",
data_mode="lazy",
column_defs=engine.make_column_defs(dims, agg),
)
# Expanding a node pushes the full `expanded_state` map; re-materialise only those
# nodes' children (lazy=True). Frontend owns expanded_state, Python owns row_data.
@callback(Output("grid", "row_data"), Input("grid", "expanded_state"))
def lazy_tree(expanded):
return engine.get_tree_payload(dims, agg, expanded=expanded or {}, lazy=True)
  • The frontend does zero math. Every node’s children are computed by the Polars engine (Dash) or the parity-verified @tensorgrid/core port; the client only splices the returned nodes into the display tree (mergeChildren).
  • Cached by stable node id. The first expand fetches; a re-expand of an already-fetched node is instant with zero network. A data/shape change (edit / regroup / filter) invalidates the cache but keeps the expanded state — the frontend owns view state, so it survives a recompute.
  • Auto-escalate. Let the engine choose the mode from a cheap node-count estimate: build_grid(data, {"rows": dims, "measures": agg, "auto_escalate": True, "node_count_threshold": 50000}) sets data_mode for you — Mode A (full tree, client-side) for a small tree, Mode B (lazy) past the threshold. The estimate is a conservative upper bound, so it can only over-escalate a borderline tree, never silently ship a huge one.
  • For a large client-side tree that still fits in one payload, use virtualization; for a huge flat source, use the infinite row model.