V2 data forms are declarative JSON documents that describe a component tree. The renderer walks the tree top-down, resolving each node’s component from the registry, evaluating conditionals and bindings, and rendering the result. This page covers the top-level form shape, the UINode interface, conditional rendering, iteration, and styling.Documentation Index
Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
Use this file to discover all available pages before exploring further.
The DataFormV2 Shape
Every V2 form has four top-level sections alongside the component tree.| Field | Type | Description |
|---|---|---|
version | "2" | Required flag that enables V2 rendering. If omitted, a non-empty nodes array also triggers V2 mode. |
nodes | UINode[] | The root-level component tree. |
scripts | Record<string, string> | Named script dictionary. Keys are names referenced by scriptRef events; values are JavaScript function bodies. |
scriptModules | Record<string, ScriptModule> | Reusable script modules with declared inputs, returns, and optional debounce. |
bridge | BridgeConfig | Permissions and configuration for the kodexa.* Bridge API. The permissions array controls which bridge methods scripts may call. |
copyRules | TaxonCopyRule[] | Optional form-level copy rules shared by every card on the form. See Form-level copy rules. |
Form-level Copy Rules
DataFormV2 accepts an optional top-level copyRules: TaxonCopyRule[] field. Cards that consume copy rules (panels, transposed grid rollups) merge form-level rules with their own per-card rules — on a sourceTaxon conflict, card-level wins as a whole (the per-card rule replaces the form-level entry for that source taxon, no field-level merge).
Use form-level rules when several panels on the same form need the same copy block — a freight review form with five-plus source panels (one per BoL and manifest) typically needs the same sourceDocumentRef / sourceBolNumber / sourceDocumentType stamp on each. Declaring the rule once at the form level avoids repeating it on every panel.
stampAttributes on copy rules
stampAttributes lives on a rule’s copyBehavior and is distinct from copyAttributes:
copyAttributes(boolean) clones existing source attributes onto the destination with content-tag preservation, so the destination keeps the source’s spatial anchors.stampAttributes(map) writes new derived attributes onto the destination — typically provenance/audit fields likesourceDocumentRef,sourceBolNumber,sourceDocumentTypethat have no source attribute to clone.
stampAttributes value is either a literal string (no ${...} placeholders) written as-is, or a ${path} template resolved against a source-row context with these accessors:
| Accessor | Resolves to |
|---|---|
source | The source DataObject being copied |
source.parent | The source’s parent DataObject |
source.idString / source.parent.idString | String(dataObject.id) — stable within the current session |
source.uuid / source.parent.uuid | The data object’s UUID |
source.<fieldName> / source.parent.<fieldName> | getFirstAttributeValue(<fieldName>) on that object |
undefined are dropped (no attribute is created). When a template expression is a single ${...}, the resolved value preserves its native type (number, boolean, date); when it’s mixed with literal text, the result is stringified.
Stamped attributes are written as plain values — they do not carry a content-node tagId link. Use copyAttributes: true for fields that should keep the source’s tag-to-content-node link.
UINode Anatomy
AUINode is the fundamental building block. Every element in a V2 form — panels, editors, labels, grids — is a UINode.
How the renderer works
SchemaRoot initializes the QuickJS script runtime, the Bridge host, and a reactive data context containing the current dataObjects and tagMetadataMap. It then walks the nodes array and renders a SchemaNode for each entry.
Each SchemaNode resolves its component from the registry, evaluates the if conditional, merges static props with dynamically evaluated bindings, wires up events as handler functions, and renders the resolved Vue component. Children and slots are rendered recursively as nested SchemaNode instances.
Conditional Rendering
V2 forms support two conditional mechanisms that control whether a node appears in the DOM.if and show (JavaScript expressions)
if removes the node from the DOM entirely when its expression evaluates to a falsy value. show keeps the node mounted but hides it with display: none.
Use
if when the node is expensive to keep mounted or when you want clean DOM output. Use show when you need the node to retain its internal state while toggled.ifFormula and showFormula (reactive KEXL formulas)
These behave the same as if and show but accept reactive KEXL formulas evaluated via the WASM document engine rather than plain JavaScript expressions. They re-evaluate automatically when referenced data attributes change, without requiring explicit watchers.
ifFormula and showFormula are planned extensions to the UINode interface. Use if and show with JavaScript expressions for current implementations.Iteration
Thefor directive renders a node once for each item in a source collection. Loop variables are injected into the data context for child expressions.
Example: rendering a panel per data object
source expression is evaluated against the current data context. Each iteration injects $item and $index (or whatever names you specify in itemAs and indexAs) into the context for use in bindings and child expressions. The key expression must produce a unique value per item to enable efficient DOM updates.
Styling
V2 nodes acceptclass and style for visual customization.
class can be a static string or a record mapping class names to binding expressions for conditional application:
style accepts either an inline CSS string or an object of style properties:
class field are the preferred approach for most styling needs.
Next Steps
Data Binding
Expressions, context variables, and reactive bindings
Layout Components
Panels, tabs, rows, columns, and alerts
Data Components
Attribute editors, tables, grids, and more
Bridge API
The kodexa.* scripting API reference
