Nested & Repeatable Fields
Two field types let you compose a DTO out of smaller pieces instead of a single flat list: "group" for a fixed set of related fields, and "array" for a repeatable list of them.
"group" — a labeled cluster of fields
A group is purely a visual and logical grouping — it does not change how values are stored. Each nested field still gets its own top-level id in the form's flat values object, exactly as if it had been declared directly on the section.
import type { FormDTO } from 'react-form-dto';
const profileForm: FormDTO = {
sections: [
{
id: 'main',
fields: [
{
id: 'address',
type: 'group',
label: 'Address',
fields: [
{
id: 'street',
type: 'text',
label: 'Street',
validations: { required: 'Street is required' },
},
{ id: 'city', type: 'text', label: 'City' },
],
},
],
},
],
};
// After submit, `data` looks like: { street: '...', city: '...' }
// — NOT { address: { street: '...', city: '...' } }.Because nested fields keep flat top-level ids:
- Their
validationsrun exactly like any other field's (including as part ofform.handleSubmit/form.trigger()). visibleWhenworks on nested fields too, and can reference fields both inside and outside the group.ids must still be unique across the entire DTO, not just within the group.
"array" — a repeatable list of items
An array field renders zero or more copies of an item template (fields), with built-in Add/Remove controls. Unlike "group", the whole list is stored as a single value:
const contactsForm: FormDTO = {
sections: [
{
id: 'main',
fields: [
{
id: 'contacts',
type: 'array',
label: 'Contacts',
fields: [
{ id: 'name', type: 'text', label: 'Name' },
{ id: 'email', type: 'email', label: 'Email' },
],
},
],
},
],
};
// values.contacts is then a list of { name, email } objectsEach item's fields are scoped to that item (no id clashes between items or with the rest of the form — name/email here don't collide with a top-level name field elsewhere).
Known limitations (for now)
- Per-item validation isn't wired into
validateAll/trigger()yet — validate array contents with a top-levelvalidatefunction on a field, or with a schema resolver, until per-item DTO validation lands. visibleWhenconditions cannot reference a specific array item (e.g. "item 0's type").- Custom renderers for the item template's field types are respected (passed through via
renderers), but there's currently no way to override the array/group container's own layout.
Custom rendering
Both types are ordinary field renderers under the hood — GroupField and ArrayField, exported from the package — so you can override either the same way you'd override any other field type:
<FormBuilder dto={myDTO} renderers={{ array: MyCustomArrayRenderer }} />