Portal Community

Read Phase (On Mount)

// 1. initialValues is the $json source:
const initialValues = {
  firstName: 'Jane',
  address: { city: 'London' }
};

// 2. Engine initialises value map from binding paths:
// Control 'first-name' has binding { source: '$json', path: 'firstName' }
//   → engine.getValue('first-name') === 'Jane'
//
// Control 'city' has binding { source: '$json', path: 'address.city' }
//   → engine.getValue('city') === 'London'

Write Phase (On User Change)

// 3. User types 'Manchester' in the city field

// ControlRenderer calls:
setFieldValue('city', 'Manchester')

// Which calls:
engine.setValue('city', 'Manchester')

// The engine fires the 'change' event with fieldId='city', value='Manchester'
// FormStateProvider re-renders; useAtlasForm() returns updated values:
// values['city'] === 'Manchester'

// The original initialValues object is NOT mutated:
// initialValues.address.city === 'London'  ← still unchanged

Submit Phase

// 4. User clicks Submit

// submitForm() runs validation, then calls onSubmit with current values:
const handleSubmit = async (values: Record<string, any>) => {
  // values is the engine's value map — NOT the original initialValues
  // values['first-name'] === 'Jane'
  // values['city']       === 'Manchester'  ← updated value

  await api.put('/applicants/42', {
    firstName: values['first-name'],
    address: {
      city: values['city'],
    }
  });
};

One-Way Binding (readOnly)

Setting readOnly: true makes the binding one-way — read on mount, but user changes do not update the value map. Use this for display-only fields that should not be submitted:

// readOnly binding — shows the value but prevents user writes
{
  "id":   "applicant-id",
  "type": "label",
  "binding": {
    "source":   "$json",
    "path":     "id",
    "readOnly": true
  }
}

// engine.getValue('applicant-id') is set from initialValues.id on mount
// If the user somehow triggers a change event (e.g., via programmatic setValue),
// readOnly does NOT prevent the write — it only disables write from user interaction

Two-Way Binding Data Flow Summary

PhaseDirectionWhat Happens
MountSource → EngineEngine reads path from source; sets initial value in value map
User changeEngine (internal)Engine updates value map; fires change event; React re-renders
SubmitEngine → HandleronSubmit(values) called with full value map; handler persists
The Source Object Is Never Mutated Atlas Forms never mutates the initialValues object you pass in. It reads from it once on mount, then maintains its own internal copy. This ensures your application state outside the form is not affected by form edits — until you explicitly call onSubmit and persist the new values yourself.