Skip to content

Render and submit nested forms

Use this guide after implementing the basic form flow. A nested form lets a submission include related data; it needs a renderer and payload that preserve the form’s relationship structure.

A grid cell can contain a full nested form instead of a single property. This is used when one submission should create a parent record plus one or more related records — for example, a Candidate form that also collects Work Experience or Education entries inline.

When a cell holds a nested form, the form key replaces property. The value is a complete nested form payload (with its own object, grids, and fields). The cell also includes settings.relation, which tells Caraer how to link the nested form’s record to the parent record after submission.

[
{ "property": { "uuid": "prop-firstname", "name": "firstname" } },
{
"form": {
"uuid": "nested-work-experience-uuid",
"object": { "uuid": "...", "name": "WorkExperience" },
"grids": [
{
"type": "step",
"grid": [
[
{ "property": { "uuid": "prop-company", "name": "company" } },
{ "property": { "uuid": "prop-role", "name": "role" } }
]
]
}
]
},
"settings": {
"relation": { "uuid": "...", "name": "has_work_experience" }
}
}
]

settings.relation is required for nested forms. Without it, the form configuration is invalid.

Treat nested forms as recursive mini-forms:

  1. When you encounter a cell with form, render that nested form’s step grid (typically the grid where type is step).
  2. Render nested form fields the same way you render top-level fields (same property types, settings, and options endpoint behavior).
  3. Nested forms can themselves contain nested forms — keep rendering recursively until you reach property cells.

If the same nested form appears more than once in a parent form (for example, two work-experience blocks), give each instance a stable index so field values do not overwrite each other. A common pattern is to namespace fields by nested form UUID and index:

  • Non-wizard parent: nested-work-experience-uuid[0].company, nested-work-experience-uuid[1].company
  • Wizard parent: step-work-history.nested-work-experience-uuid[0].company

On submit, keep the same overall form structure you fetched — do not flatten nested fields to the parent level. Values belong on the nested form’s property cells inside form.grids.

For each nested form instance:

  1. Locate the corresponding form cell in the parent grid.
  2. Walk the nested form’s grids recursively.
  3. Set value on each nested property cell (and optionally on property.value).

Example submit fragment with one nested form instance:

[
{
"property": { "uuid": "prop-firstname", "name": "firstname" },
"value": "Jane"
},
{
"form": {
"uuid": "nested-work-experience-uuid",
"object": { "uuid": "...", "name": "WorkExperience" },
"grids": [
{
"type": "step",
"grid": [
[
{
"property": { "uuid": "prop-company", "name": "company" },
"value": "Acme Corp"
},
{
"property": { "uuid": "prop-role", "name": "role" },
"value": "Software Engineer"
}
]
]
}
]
},
"settings": {
"relation": { "uuid": "...", "name": "has_work_experience" }
}
}
]

When the same nested form UUID appears multiple times, preserve grid order and map each instance to the matching index in your frontend state ([0], [1], etc.).

The backend processes nested forms in two stages:

  1. Parent record — fields on the outer form are validated and saved to the parent form’s target object.
  2. Inner forms — for each grid cell containing form, Caraer submits that nested form as its own submission, creates a record for the nested form’s object, and links it to the parent record using settings.relation.

This means nested form fields are not stored on the parent record. They become separate related records in your graph.

  • Omitting settings.relation on nested form cells.
  • Flattening nested values to the parent payload instead of nesting them under form.grids.
  • Reusing the same field namespace for multiple nested form instances, causing values to collide.
  • Expecting nested form properties to appear on the parent record after submit.