Skip to content

Nested Form ​

The nestedform field renders a whole form inside one field. On a JSON attribute it saves the inner fields as one object, and on a relation it edits the related record.

JSON object ​

The form option takes the same definition as any form, inline or as the path to a YAML file, and the inner fields can be of any type. Each inner field is named inside the field, such as address[line1], and the field saves them together as one object, such as {"recipient": "...", "line1": "..."}.

yaml
fields:
    address:
        label: Address
        type: nestedform
        comment: Saved on the sample as one JSON object.
        form:
            fields:
                recipient:
                    label: Recipient
                line1:
                    label: Street
                suburb:
                    label: Suburb
                    span: left
                region_code:
                    label: Postal Code
                    span: right

The attribute must hold JSON. On an October Rain model, list it in $jsonable, as the Sample model does for every structured field on these pages. On a plain Eloquent model, give it an array cast. See Models for both.

php
/**
 * @var array<int, string> jsonable attributes stored as JSON for the structured fields.
 */
protected $jsonable = [
    'features',
    'permissions',
    'interests',
    'tags',
    'topics',
    'content',
    'steps',
    'address',
    'line_items',
    'meta',
    'shipping',
    'contact',
    'faqs',
    'highlights',
    'milestones',
    'dimensions',
    'sections',
    'specs',
    'itinerary',
    'languages',
    'deliveries',
    'variants',
    'stockists',
    'parts',
    'price_breaks',
    'bundle_items',
    'suppliers',
    'components',
    'stock_levels',
    'reviews',
    'spec_sheet',
    'certifications',
    'awards',
    'seo',
    'packaging',
];

Tabs ​

The inner form can have tabs and secondaryTabs of its own, beside or instead of its fields. Its tabs are styled as nested tabs, so they read as part of the field rather than the page.

yaml
fields:
    shipping:
        label: Shipping
        type: nestedform
        comment: The nested form brings its own tabs.
        form:
            fields:
                recipient:
                    label: Recipient
            tabs:
                fields:
                    line1:
                        label: Street
                        tab: Street
                    suburb:
                        label: Suburb
                        span: left
                        tab: Street
                    region_code:
                        label: Postal Code
                        span: right
                        tab: Street
                    instructions:
                        label: Delivery Instructions
                        type: textarea
                        size: tiny
                        tab: Delivery
                    leave_at_door:
                        label: Leave at the door
                        type: switch
                        tab: Delivery

Without the panel ​

The inner form sits in a panel by default, with a border and a background. showPanel: false drops the panel, so the inner fields line up with the rest of the form while still saving as one object.

yaml
fields:
    contact:
        label: Contact
        type: nestedform
        showPanel: false
        form:
            fields:
                person:
                    label: Person
                    span: left
                phone:
                    label: Phone
                    span: right

Relation ​

When the field name is a relation on the model, the inner form edits the related record instead of a JSON value. Here primary_group is a belongsTo relation, so the inner fields are the group's own name and code. Saving the form saves the group as well, and a validation error on the group shows on its inner field.

yaml
fields:
    primary_group:
        label: Primary Group
        type: nestedform
        comment: Editing these fields changes the group itself, which saves with the sample.
        form:
            fields:
                name:
                    label: Name
                    span: left
                code:
                    label: Code
                    span: right
php
/**
 * @var array<string, mixed> belongsTo relations, the owner, reviewer, group and category picked by the relation widgets.
 */
public $belongsTo = [
    'user' => User::class,
    'reviewer' => User::class,
    'primary_group' => UserGroup::class,
    'primary_category' => Category::class,
];

The field suits a singular relation, such as belongsTo or hasOne. While the relation is empty, the inner fields start blank. defaultCreate: true instead creates a record and attaches it as the form loads (against the session key on a Rain model), so the inner form always edits a record the relation holds.

Preview ​

disabled renders the inner form in preview mode, and the field is left out of the save. This copy reads the address through valueFrom.

yaml
fields:
    address_preview:
        label: Address
        type: nestedform
        valueFrom: address
        disabled: true
        form:
            fields:
                recipient:
                    label: Recipient
                line1:
                    label: Street
                suburb:
                    label: Suburb
                    span: left
                region_code:
                    label: Postal Code
                    span: right

Options ​

OptionDescription
formthe inner form, with fields, tabs and secondaryTabs, inline or as the path to a YAML file.
showPanelwraps the inner form in a panel. Default: true.
defaultCreateon a relation, creates and attaches a related record when there is none. Default: false.

The field also takes the common field properties, such as disabled and valueFrom.