Atlas Forms
The Binding Object
The binding property on a form control is a small configuration object with four fields: source, path, readOnly, and an optional transform. Together these four fields fully define how the control connects to external data.
ControlBinding Type
// packages/types-js/src/form.types.ts
interface ControlBinding {
/** The data source to read from and write to */
source: '$json' | '$context';
/** Dot-notation path within the source object */
path: string;
/** If true: reads from source on load, but does NOT write back on change */
readOnly?: boolean;
/** Optional transform pair applied on read and write */
transform?: {
/** Applied when reading from the source — format for display */
read?: string; // Named transform registered with registerBindingTransform()
/** Applied when writing to the source — parse before save */
write?: string; // Named transform registered with registerBindingTransform()
};
}
Minimal Binding
{
"binding": {
"source": "$json",
"path": "applicant.firstName"
}
}
Read-Only Binding
// Shows the value but does not write it back when the user changes it
// Useful for displaying context data alongside editable fields
{
"id": "tenant-name",
"type": "label",
"binding": {
"source": "$context",
"path": "tenant.displayName",
"readOnly": true
}
}
Binding With Transform
// Display a stored ISO date string (2026-01-15) as a localised date (15 Jan 2026)
// Parse the user's localised input back to ISO before saving
{
"id": "contract-date",
"type": "date-picker",
"binding": {
"source": "$json",
"path": "contract.startDate",
"transform": {
"read": "isoToLocaleDate", // registered transform
"write": "localeDateToIso" // registered transform
}
}
}
Field Reference
| Field | Required | Default | Notes |
|---|---|---|---|
source | Yes | — | $json or $context |
path | Yes | — | Dot-notation path; may include array indexing |
readOnly | No | false | When true, user edits do not update the form's value map for this field |
transform.read | No | — | Named transform applied when reading the raw value from source |
transform.write | No | — | Named transform applied when writing user input back to the value map |
Controls Without a Binding
Omitting the binding property is valid and common for display-only controls (labels, dividers, articles, charts) and for controls whose values are not persisted (e.g., a search bar that filters an in-page list):
// No binding — value is local to the form and not submitted
{
"id": "search-filter",
"type": "text",
"placeholder": "Search..."
// binding omitted: value held in form state but not written to any external path
}
No Binding ≠ No Value
A control without a binding still participates in form state — its value is in
engine.getValues() keyed by its id. It simply does not read from or write to an external path. Your submit handler can still read it from values['search-filter'].