Zova Table Controller Render Deep Dive
This page is a small lower-level supplement for the Zova Table runtime.
Use it when you already understand the broader table architecture and now want to inspect the controller micro-pipeline more precisely:
- how
ControllerTableboots - how visible columns and render functions are assembled
- how
tableCellrender providers are normalized and resolved - how cell render preparation and transient-object handoff work
Why this supplement exists
The existing table docs already cover the broad architecture well:
What those pages do not isolate directly is the controller/render micro-pipeline inside ControllerTable.
That is the only gap this supplement fills.
The shortest accurate mental model
A practical mental model is:
BeanControllerTableBase.$useTable(...)owns the TanStack bridge at controller levelControllerTable.__init__()prepares schema properties, metadata, columns, and the table instance_createTableMeta()decides which properties are visible and which render function each one should use_createColumnRender()resolves either atableCellbean-backed render path or a general render targetcellRenderPrepare()can preload nested bean-backed renders_cellRender()/_cellRenderInner()hand off row/cell scope, fallback values, and transientgetValue(...)state into final rendering
That means the controller micro-pipeline is where schema, visibility, bean resolution, and render contexts finally converge.
Source-confirmed reading path
When reading this topic, use this order:
zova/src/suite-vendor/a-zova/modules/a-table/src/lib/beanControllerTableBase.tszova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsxzova/src/suite-vendor/a-zova/modules/a-table/src/types/tableCell.tszova/src/suite-vendor/a-zova/modules/a-table/src/types/tableColumn.tszova/packages-utils/zova-jsx/src/lib/zovaJsx.tszova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionOperationsRow.tsx
That order moves from the controller/TanStack bridge, to the main controller runtime, to the render contracts, to the JSX runtime handoff, and finally to a concrete tableCell specimen.
BeanControllerTableBase.$useTable(...)
The TanStack bridge lives in:
zova/src/suite-vendor/a-zova/modules/a-table/src/lib/beanControllerTableBase.tsThe key source-confirmed behavior is:
useVueTable(...)is called insideinstanceScope(...)- the returned table instance is
markRaw(...)
This is the first important lower-level rule:
- the table instance is still controller-owned runtime
- TanStack is the underlying table engine, but the controller remains the effective Zova runtime owner
ControllerTable.__init__() boot sequence
The main runtime file is:
zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsxThe source confirms this boot sequence:
- register
$$table - create the CEL environment and
ZovaJsxinstance - create schema-driven properties
- refresh metadata
- watch
schemafor meta refresh - create the TanStack table instance
That is the core controller-level assembly path.
_createTableMeta() as visible-column/render assembly point
Inside the same controller, _createTableMeta() is the clearest metadata-assembly step.
It:
- iterates schema-derived properties
- builds column scope
- builds render context
- merges top-level column props
- checks visibility
- creates per-column render functions
- stores the surviving visible properties and render map in
tableMeta
This is the most important micro-pipeline rule:
- schema properties do not automatically become rendered columns
- they are filtered and converted through controller-owned metadata assembly first
getRenderProvider() normalization and _createColumnRender()
The render-resolution path also lives in ControllerTable.
It decides whether a column render should be treated as:
- text fallback
- a general render target
- a
tableCellbean-backed renderer
_createColumnRender() is the main resolution point where:
- render provider is normalized
- bean-backed providers are resolved
- decorator options are merged
- visibility hooks such as
checkVisible(...)can participate
This is the lower-level rule to remember:
- render resolution is not only “take whatever the schema says”
- the controller resolves and normalizes that render contract first
cellRenderPrepare() and nested render preloading
cellRenderPrepare() is the preloading step for bean-backed renderers.
This matters most for nested or action-heavy cells, because it lets the controller prepare the concrete tableCell beans before final render.
A practical reading rule is:
cellRenderPrepare()is part of render readiness, not only a cosmetic helper
A good current specimen is:
basic-table/src/bean/tableCell.actionOperationsRow.tsx
because it prepares the nested row-action render set based on visibility.
_cellRender() / _cellRenderInner() and transient value handoff
The final cell rendering path uses:
- column scope
- cell scope
- fallback value
- actual cell value
- transient
getValue(...)handoff throughZovaJsx
This is where the lower-level scope handoff matters most.
The current runtime uses the ZovaJsx transient-object path so cell renderers can see the active value context while still staying inside the controller-driven runtime.
A practical reading rule is:
- the final cell render is not only a plain function call
- it is a scoped runtime handoff with controller-owned context
Table-cell contract in types
The render contracts live in:
a-table/src/types/tableCell.tsa-table/src/types/tableColumn.ts
These files confirm the lower-level boundary types for:
ITableCellRendercheckVisible(...)- column scope vs cell scope
- render contexts passed into cell renderers
That makes them the right files to read when the runtime feels confusing even though the broad table docs are already understood.
Concrete specimen: operations-row tableCell
A good concrete specimen is:
zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionOperationsRow.tsxThis file is useful because it shows several lower-level pieces in one place:
checkVisible(...)- permission-based render filtering
- nested render preparation
- final action-row rendering through the table cell contract
So it is the best small specimen for understanding why the micro-pipeline matters in practice.
What this page does not re-explain
This supplement does not fully re-explain:
- broad table authoring -> see Table Guide
- full runtime architecture -> see Zova Table Under the Hood
- general file-order map -> see Zova Table Source Reading Map
- row/bulk permission semantics -> see Table Action Visibility and Permission Flow Guide
Its job is only to explain the controller/render micro-pipeline.
Where to read next
Use these next steps depending on your question:
- if you want the broad table runtime again, read Zova Table Under the Hood
- if you want the file-order map, read Zova Table Source Reading Map
- if you want row/bulk visibility behavior, read Table Action Visibility and Permission Flow Guide
- if you want the list-page runtime that feeds
ZTable, read Resource List Page Deep Dive
Final takeaway
The most accurate way to read this lower-level table supplement is:
BeanControllerTableBaseowns the TanStack bridge at controller scopeControllerTableowns metadata assembly and render resolutiontableCellbeans participate through explicit controller-managed resolution and scope handoffcellRenderPrepare()and_cellRender()are part of the real runtime pipeline, not only helper details
That is the source-confirmed controller/render micro-pipeline in the current Cabloy Basic table runtime.