Atlas Forms
Shared Binding Paths
Two or more controls can bind to the same path in the same source. When the user changes either control, the other reflects the update immediately. This is the foundation of the quick-pick pattern — a shortcut selector that pre-fills a text field.
How Shared Paths Work
Both controls read the same initial value on mount. When either control fires a change, the engine updates the shared value in its map and both controls re-render with the new value. The last write wins.
Quick-Pick Pattern
A common use case: a free-text input paired with a button group that lets the user quickly select common values without typing:
// Schema — two controls sharing the same binding path
{
"controls": [
// Button group — quick-pick shortcuts
{
"id": "reason-quick-pick",
"type": "button-group",
"label": "Common Reasons",
"options": [
{ "value": "Incorrect address", "label": "Wrong address" },
{ "value": "Duplicate entry", "label": "Duplicate" },
{ "value": "Missing information", "label": "Incomplete" }
],
"binding": {
"source": "$json",
"path": "rejectionReason"
}
},
// Free-text input — manual entry
{
"id": "reason-text",
"type": "textarea",
"label": "Rejection Reason",
"placeholder": "Select above or type a custom reason...",
"binding": {
"source": "$json",
"path": "rejectionReason" // ← same path
}
}
]
}
Interaction Flow
- Form loads: both controls read
$json.rejectionReason— both show the same initial value - User clicks "Duplicate" in the button group:
engine.setValue('reason-quick-pick', 'Duplicate entry') - Engine updates the value map;
reason-textre-renders showing "Duplicate entry" - User edits the textarea to "Duplicate entry (system error)":
engine.setValue('reason-text', 'Duplicate entry (system error)') - Engine updates the value map; button group re-renders — no button is active (custom value)
- On submit:
values['reason-text']==='Duplicate entry (system error)'
Important: Values Are Keyed by Control ID
Even though both controls share the same binding path, they have different control IDs. The value map contains both keys:
// After user selects "Duplicate" from the button group:
engine.getValues() === {
'reason-quick-pick': 'Duplicate entry',
'reason-text': 'Duplicate entry',
}
// After user edits the textarea:
engine.getValues() === {
'reason-quick-pick': 'Duplicate entry', // ← NOT updated (user didn't touch it)
'reason-text': 'Duplicate entry (system error)', // ← updated by user
}
Submit the Control That Owns the Final Value
When using the quick-pick pattern, your submit handler should read from the textarea (
reason-text), not from the button group. The textarea is the "primary" control that the user edited last. Alternatively, use engine.getComputedValue() with an expression that resolves which control was last modified.