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 oncerows: [region, country]measures: revenue: sum cost: sumcalculated: margin: (revenue - cost) / revenue # safe formula DSL — no code executionformats: revenue: currency:USD cost: currency:USD margin: percentage:1conditional_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_pctgrand_total: truefrom dash import Dashfrom 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"],)import { TensorGrid } from '@tensorgrid/react';
// The adapters mirror the config keys as camelCase props (conditional_formats splits into// colorScales / dataBars / iconSets; style_rules -> cellStyles).<TensorGrid data={data} rows={['region', 'country']} measures={{ revenue: 'sum', cost: 'sum' }} calculated={{ margin: '(revenue - cost) / revenue' }} formats={{ revenue: '$0,0', cost: '$0,0', margin: '0.0%' }} colorScales={{ revenue: { min: '#fff5f5', max: '#2f9e44' } }} cellStyles={{ margin: [{ op: '<', value: 0.2, style: { color: '#b42318' } }] }} windowColumns={[{ kind: 'pctOfTotal', by: 'revenue', as: 'revenue_pct', format: '0.0%' }]} grandTotal/>;<TensorGrid :data="data" :rows="['region', 'country']" :measures="{ revenue: 'sum', cost: 'sum' }" :calculated="{ margin: '(revenue - cost) / revenue' }" :formats="{ revenue: '$0,0', cost: '$0,0', margin: '0.0%' }" :color-scales="{ revenue: { min: '#fff5f5', max: '#2f9e44' } }" :cell-styles="{ margin: [{ op: '<', value: 0.2, style: { color: '#b42318' } }] }" :window-columns="[{ kind: 'pctOfTotal', by: 'revenue', as: 'revenue_pct', format: '0.0%' }]" grand-total/>import { mountTensorGrid } from '@tensorgrid/vanilla';
mountTensorGrid(document.getElementById('grid'), { data, rows: ['region', 'country'], measures: { revenue: 'sum', cost: 'sum' }, calculated: { margin: '(revenue - cost) / revenue' }, formats: { revenue: '$0,0', cost: '$0,0', margin: '0.0%' }, colorScales: { revenue: { min: '#fff5f5', max: '#2f9e44' } }, cellStyles: { margin: [{ op: '<', value: 0.2, style: { color: '#b42318' } }] }, windowColumns: [{ kind: 'pctOfTotal', by: 'revenue', as: 'revenue_pct', format: '0.0%' }], grandTotal: true,});Config keys
Section titled “Config keys”Every key is optional except the dimensions. The Dash config is the single source of truth; the adapters expose the same knobs as options.
- Dimensions —
rows(row tree) andcolumns(the pivot axis).hierarchiesnames a reusable, fixed-order level group referenced fromrows/columns. - Measures —
measuresfor base aggregations (sum/mean/quantile:0.9/ …);calculatedfor post-aggregation ratios via the safe formula DSL,sql, a browserjsexpression, or (withallow_code=True) apython/python_codecallable. - Display —
formats(thekind[:arg]format DSL —currency:USD/percentage:1),headers, andfilters.cell_renderersswaps a column’s presentation (badge, progress bar, sparkline) while the value stays raw. - Conditional formatting —
conditional_formats(colorScale/dataBar/iconSet, see conditional formatting) andstyle_rules(discreteif-formula →style/className). - Tree transforms (grid flow only) —
top_nrolls the tail into an “Others” node;window_columnsderivesrunning_total/rank/pct_of_total/pct_of_parent/delta/macolumns;havingprunes groups by a measure predicate;grand_totalprepends a total row. - Derived dimensions —
binscuts a numeric column into labeled ranges;date_partsderives groupableyear/quarter/month/ … columns from a temporal column. - Pivot knobs —
col_subtotals,grand_total,row_grand_total, andcontext(percent-of column / row / total) apply when acolumnsaxis is present.
The full schema with every accepted key lives in the config reference.
- Safe by default. DSL,
sql, andjsmeasures are parsed into expressions and never execute arbitrary code. Thepython/python_codeforms DO run code, so they are refused unless you passallow_code=True— enable it only for configs you trust, never for end-user input. - The engine does the math.
build_grid/from_configproducerow_data/column_defsfrom Polars; the frontend only renders. Adapter props map onto the parity-verified@tensorgrid/coreport, so the same config yields the same numbers everywhere. window_columns/top_n/havingare row-tree transforms — they are refused on a pivot (columns) config rather than silently ignored.