Sections and tabs
A Section holds fields and shows them together on the form, in a bordered box under its label, as a Group does. Tabs hold sections and show one of them at a time, as tabs or as an accordion.
Use them when a form grows long, or when a set of fields belongs together. A Book might keep its Edition details (print run, binding, ISBN) in a section that only appears when Special edition is switched on, and split everything else into Details, Sales and SEO tabs.
Fields stay where they are
A section only arranges fields. The fields inside it are stored exactly as if the section weren't there:
- A section at the top of a fieldset holds top-level fields. Each keeps its own key, its own stored value, and its own place in templates and dynamic data.
@post(isbn)reads the ISBN whether or not it sits in a section. - A section inside a Group or a Repeater row holds keys of that group or row.
So you can move fields into a section, between sections, or out again at any time. Nothing is migrated, and nothing that reads the values notices.
Because the fields share their scope with everything beside the section, a key must be unique across the whole scope, the fields in other sections and tabs included. The section's own key is only its name in the fieldset: nothing is stored under it, and it never appears in templates or dynamic data.
Sections
- Description shows as any field's does: the fieldset's Display field description as setting puts it in a tooltip beside the label or under it. A section without a label shows it above the box.
- Columns: a section can take a column width like any field, so two half-width sections sit side by side. The fields inside lay out on the section's own row grid. See Form layout and columns.
The label is optional: without one, the section is just the box.
To let people fold a set of fields away, put it in a Tabs field shown as Accordion. With one section inside, that's a single panel that opens and closes.
Tabs
Show as picks Tabs on top, Tabs on the side or Accordion. Each section inside the Tabs field is one tab: its label names the tab and its description opens the tab's content. A section's column setting doesn't apply inside tabs.
Tabs adapt to the space they get. Where the form is narrow, such as the block editor's default sidebar, tabs show as an accordion, and side tabs move to the top before that. Each tab remembers, per browser, which tab was last open.
Tabs hold only sections, but a section inside tabs can hold any field, including another Tabs field.
Showing and hiding a whole section
Give a section (or a Tabs field) conditional logic, and it shows or hides every field it holds. A section hidden inside tabs drops its tab. Hidden fields keep their stored values, as any hidden field does.
Fields in different sections can refer to each other in their rules, since they share a scope. A section can't use a field it holds as a source, because hiding the section would hide the source too.
Errors in another tab
Each tab shows a badge when fields inside it have problems. When a save finds a problem in another tab, and the tab you're on has none, that tab comes forward.
Arranging fields in the builder
In VX → Fieldsets, the fields a section holds are indented under it, as a Group's are, so you can see at a glance what belongs together. Each card has a menu: click More actions (⋯) on the card, or right-click it.
- Drag a field into a section, out of it, or between sections. The builder only lets a field go where its value would stay where it is, so you can't drag a field into a Group this way.
- Move to, in a field's menu, does the same without dragging. It lists every other place the field can go: each section and Tabs field at its level, and the level itself (the top level, or the Group or Repeater the field is in). The field goes to the end of the section it joins, or just after the section it leaves. Tabs take only sections, so they're listed for a section alone. A section that shows or hides by the field can't hold it: the builder says so and leaves the field where it is. To move several fields at once, turn on selection, tick them, and choose Bulk actions → Move to: they go together and keep their order, or, if one of them can't go there, none of them moves.
- Wrap fields that sit side by side: turn on selection, tick them, and choose Bulk actions → Wrap in section.
- Ungroup a section from its menu: its fields take its place, and the section is removed. Since tabs hold only sections, a tab's menu offers this only when the tab holds nothing but sections.
- Collapse all and Expand all next to the search box fold every section, Tabs, Group and Repeater in the list. The builder remembers, per browser and per fieldset, which ones you left folded or open, through saves and reloads.
Fields in a section at the top level are top-level fields in every other way too. Renaming one's key offers to move its stored values.
Each also has its own REST API settings, and the REST API returns its value under its own key, as if the section weren't there.
Limits
- Deleting a section deletes the fields it holds. Their stored values are left in the database, and Meta Watch lists them.
- A field can't switch to Section or Tabs, or back, through Switch type: that would move where the fields it holds are stored. A Section switches to Tabs only when it holds nothing but sections.
- A Field Table can't hold a section: its columns are fields.
Related
Technical details for LLMs
- Type keys:
ui_section(labeloptional ≤ 200,description≤ 2,000,fields,width/responsive_widths,conditional_logic);ui_tabs(labeloptional,display:top|left|accordion,fields:ui_sectiononly,width/responsive_widths,conditional_logic). Categorylayout;stores_data: false;layout_container: trueinvx-framework/get-field-types. - Scope: a container's
fieldsbelong to the scope the container sits in. Keys are unique across that scope, container keys included. Rule paths never include a container key (group.child, notgroup.section.child). A container's rule may not name a field it holds; a field's visibility is its own rule AND every container it sits in. - Storage: the container stores nothing. Values are stored under the fields' keys as if the containers were absent (top-level meta keys, or keys of the group / repeater row JSON). Every value pipeline (dynamic data, abilities' value reads and writes, PHP
->field()) reads the fieldset with containers already replaced by their fields. - Abilities:
vx-framework/add-fieldswithparentset to a section's or tabs' key adds inside it (tabs accept onlyui_section).vx-framework/delete-fieldson a container also removes every field it holds and lists them indeleted; their values are orphaned, not deleted.vx-framework/reorder-fieldswithparentreorders inside a container.vx-framework/move-fields(keys,parent,after) moves fields into, out of or between containers in the scope they're stored in, and refuses a move that would cross a Group or Repeater. - PHP blueprints:
Field::section( $key )andField::tabs( $key ), with->fields( [...] ).