Data Binding¶
Data binding connects UI components to application state using JSON Pointer paths (RFC 6901). It's what allows A2UI to efficiently define layouts for large arrays of data, or to show updated content without being regenerated from scratch.
Structure vs. State¶
A2UI separates:
- UI Structure (Components): What the interface looks like
- Application State (Data Model): What data it displays
This enables: reactive updates, data-driven UIs, reusable templates, and bidirectional binding.
The Data Model¶
Each surface has a JSON object holding state:
{
"user": {"name": "Alice", "email": "alice@example.com"},
"cart": {
"items": [{"name": "Widget", "price": 9.99, "quantity": 2}],
"total": 19.98
}
}
JSON Pointer Paths¶
Syntax:
/user/name- Object property/cart/items/0- Array index (zero-based)/cart/items/0/price- Nested path
Example:
/user/name→"Alice"/items/0→"Apple"
Literal vs. Path Values¶
Literal (fixed):
Data-bound (reactive):
When /user/name changes from "Alice" to "Bob", the text automatically updates to "Bob".
Reactive Updates¶
Components bound to data paths automatically update when the data changes:
Initial: /order/status = "Processing..." → displays "Processing..."
Update: Send dataModelUpdate with status: "Shipped" → displays "Shipped"
No component updates needed—just data updates.
Dynamic Lists¶
Use templates to render arrays:
{
"id": "product-list",
"component": {
"Column": {
"children": {"template": {"dataBinding": "/products", "componentId": "product-card"}}
}
}
}
Data:
Result: Two cards rendered, one per product.
Scoped Paths¶
Inside a template, paths are scoped to the array item:
For /products/0, /name resolves to /products/0/name → "Widget"
For /products/1, /name resolves to /products/1/name → "Gadget"
Adding/removing items automatically updates the rendered components.
Input Bindings¶
Interactive components update the data model bidirectionally:
| Component | Example | User Action | Data Update |
|---|---|---|---|
| TextField | {"text": {"path": "/form/name"}} |
Types "Alice" | /form/name = "Alice" |
| CheckBox | {"value": {"path": "/form/agreed"}} |
Checks box | /form/agreed = true |
| MultipleChoice | {"selections": {"path": "/form/country"}} |
Selects "Canada" | /form/country = ["ca"] |
Best Practices¶
1. Use granular updates - Update only changed paths:
2. Organize by domain - Group related data:
3. Pre-compute display values - Agent formats data (currency, dates) before sending: