Skip to content

Declarative YAML / dict config

Keep your data in code and the view in a config. One declarative mapping — a Python dict, a YAML file, or a YAML/JSON string — describes the entire grid: dimensions, measures, calculated measures, formats, filters, conditional formatting, tree transforms, and the pivot cross-tab. build_grid hands it to the Polars engine, which does all the math and returns a ready row_data / column_defs payload — the app code stays tiny.

The same config is just plain data — a dict inline, or the identical structure as a table.yaml loaded by path:

# table.yaml — the whole grid, declared once
rows: [region, country]
measures:
revenue: sum
cost: sum
calculated:
margin: (revenue - cost) / revenue # safe formula DSL — no code execution
formats:
revenue: currency:USD
cost: currency:USD
margin: percentage:1
conditional_formats:
revenue: {type: colorScale, colors: ["#fff5f5", "#2f9e44"]}
style_rules:
margin:
- {if: "margin < 0.2", style: {color: "#b42318"}}
window_columns:
- {kind: pct_of_total, by: revenue} # derived read-only column -> revenue_pct
grand_total: true
from dash import Dash
from dash_tensor_grid import TensorGrid, build_grid
# A YAML path, a YAML/JSON string, or a plain dict — all accepted.
payload = build_grid(sales, "table.yaml")
# equivalently: GridDataEngine(sales).from_config(cfg_dict)
app = Dash(__name__)
app.layout = TensorGrid(
id="grid",
row_data=payload["row_data"],
column_defs=payload["column_defs"],
**payload["options"],
)

Every key is optional except the dimensions. The Dash config is the single source of truth; the adapters expose the same knobs as options.

  • Dimensionsrows (row tree) and columns (the pivot axis). hierarchies names a reusable, fixed-order level group referenced from rows / columns.
  • Measuresmeasures for base aggregations (sum / mean / quantile:0.9 / …); calculated for post-aggregation ratios via the safe formula DSL, sql, a browser js expression, or (with allow_code=True) a python / python_code callable.
  • Displayformats (the kind[:arg] format DSL — currency:USD / percentage:1), headers, and filters. cell_renderers swaps a column’s presentation (badge, progress bar, sparkline) while the value stays raw.
  • Conditional formattingconditional_formats (colorScale / dataBar / iconSet, see conditional formatting) and style_rules (discrete if-formula → style / className).
  • Tree transforms (grid flow only) — top_n rolls the tail into an “Others” node; window_columns derives running_total / rank / pct_of_total / pct_of_parent / delta / ma columns; having prunes groups by a measure predicate; grand_total prepends a total row.
  • Derived dimensionsbins cuts a numeric column into labeled ranges; date_parts derives groupable year / quarter / month / … columns from a temporal column.
  • Pivot knobscol_subtotals, grand_total, row_grand_total, and context (percent-of column / row / total) apply when a columns axis is present.

The full schema with every accepted key lives in the config reference.

  • Safe by default. DSL, sql, and js measures are parsed into expressions and never execute arbitrary code. The python / python_code forms DO run code, so they are refused unless you pass allow_code=True — enable it only for configs you trust, never for end-user input.
  • The engine does the math. build_grid / from_config produce row_data / column_defs from Polars; the frontend only renders. Adapter props map onto the parity-verified @tensorgrid/core port, so the same config yields the same numbers everywhere.
  • window_columns / top_n / having are row-tree transforms — they are refused on a pivot (columns) config rather than silently ignored.