Field Collection Component
Purpose
The field-collection component edits an array field inside a form. It renders one template per array item and supports add, soft or hard remove, remove-all, drag-and-drop reorder, item defaults, list/grid/accordion item layouts, and grouped collections.
Use it for repeated sub-records such as line items, contacts, business hours, accessorial rows, or task lists.
Compact hierarchical rows
Accordion collections now render compact, hierarchical rows. Optional itemIcon,
itemSubtitle, itemBadges, and itemNestedCount props add an icon tile, muted metadata,
semantic badges, and a collapsed nested-record count. Badges support danger, warning,
info, success, primary, and neutral theme colors plus a template-driven when guard.
Setting label enables a collection header with an item-count chip, a summaryTemplate
subline, and Expand all / Collapse all controls. The add action moves into this header unless
addButton.position is explicitly set. Nested collections render a compact section header and
default to collapsed accordion rows; use collapseNested: false or an explicit layout to keep
the previous expanded behavior.
When itemTitle is omitted, autoItemTitle defaults to true and derives a useful title from
the first label-like scalar field (name, title, label, or description) plus up to two
metadata values. Newly added blank records open automatically. density accepts compact
(default) or comfortable.
Source updates
Frontend updates added group-level grid controls and keyboard-friendly reorder controls for grouped collections:
groupColscontrols how many groups render per row.groupSpacingcontrols Material UI grid spacing between group columns.showMoveButtonsrenders up/down controls whenoptions.allowReorderis true.options.removeTypecontrols whether individual row removal soft-deletes the row withisDeleted: trueor physically removes it from the array.- Reorderable object rows get a stable internal
_uuidonly when drag handles or move buttons are shown, so reordering follows the row instead of repainting by array index. Non-reorder collections keep their payloads untouched.
Group props only affect groupMode: true; item layout inside each group still uses layout, cols, and spacing.
Props
fieldName(string, required): Form array field binding.itemTemplate(component or component array, required): Template rendered for each item.itemType(object | string | number | boolean | auto): Type of item to create and edit. Defaults toobject.options.allowAdd(boolean): Show add button. Defaults totrue.options.allowRemove(boolean): Show remove buttons. Defaults totrue.options.allowRemoveAll(boolean): Show remove-all button. Defaults tofalse.options.allowReorder(boolean): Enable drag-and-drop reorder. Defaults totrue.options.minItems/options.maxItems(number): Minimum and maximum item counts.options.removeType(soft | hard): Individual remove behavior. Defaults tosoft, which marks object rows withisDeleted: true; usehardto splice the item out of the array.addButton.label,addButton.icon,addButton.variant,addButton.position: Add button customization.removeButton.label,removeButton.icon,removeButton.variant: Remove button customization.defaultItem(any): Default values for newly added items.onItemAdd(action list): Runs after adding an item withitem,index,fieldName, andparentItemvariables.onItemRemove(action list): Runs after soft or hard removal with the removeditem, itsindex,fieldName, andparentItem.dotsMenu.items(array): Replaces the built-in Delete-only menu. Each item supportslabel,disabled,permission,onClick, andremove; useremove: trueto invoke the configured collection removal behavior.layout(list | grid | accordion): Item layout mode. Defaults tolist.cols(number): Item grid columns whenlayout: grid.spacing(number): Spacing between items.groupMode(boolean): Enable grouping.groupBy(string): Item field used as the group key.groups(array): Group definitions withkey,label, and optionalicon.groupTemplate(component): Optional custom group header template.groupCols(number or breakpoint object): Number of group columns. Example:2or{ xs: 1, md: 2, lg: 4 }. Defaults to1.groupSpacing(number): Spacing between group columns. Defaults to0.showIndex(boolean): Show item index numbers.showDragHandle(boolean): Show drag handles.showMoveButtons(boolean): Show up/down move buttons for accessible reordering. Requiresoptions.allowReorder: true.showDivider(boolean): Show dividers between list items.containerClass/itemClass(string): CSS class hooks.itemTitle(string): Field name or template for accordion item title.defaultExpanded(boolean): Expand accordion items by default.label(localized string): Section label above the collection.itemIcon/itemSubtitle(string templates): Optional accordion icon and metadata.itemBadges(array): Inline semantic badges withlabel, optionalcolor, and optionalwhen.itemNestedCount(string template): Collapsed-row nested-record count.nestedCountLabel(localized string): Nested-count wording.summaryTemplate(string template): Header summary; receivescountanditems.showCount/showExpandAll(boolean): Header count and bulk expansion controls; both default totrue.collapseNested(boolean): Collapse nested collections by default. Defaults totrue.autoItemTitle(boolean): Derive titles from record fields. Defaults totrue.density(compact | comfortable): Accordion row padding preset.
Grouped multi-column example
component: field-collection
name: businessHours
props:
fieldName: businessHours
groupMode: true
groupBy: dayOfWeek
groupCols:
xs: 1
md: 2
lg: 4
groupSpacing: 2
groups:
- key: 1
label: { en-US: Monday }
- key: 2
label: { en-US: Tuesday }
- key: 3
label: { en-US: Wednesday }
- key: 4
label: { en-US: Thursday }
- key: 5
label: { en-US: Friday }
- key: 6
label: { en-US: Saturday }
- key: 0
label: { en-US: Sunday }
options:
allowAdd: true
allowRemove: true
allowReorder: true
removeType: soft
defaultItem:
startTime: "09:00:00"
endTime: "17:00:00"
layout: accordion
itemTemplate:
component: layout
props:
cols: 2
spacing: 2
children:
- component: field
name: startTime
props:
type: time
label: { en-US: Start }
- component: field
name: endTime
props:
type: time
label: { en-US: End }
Behavior notes
- When individual removal is available, each item shows a theme-colored three-dots menu with a Delete action. This applies to list/grid rows and accordion headers; the configured
removeType,minItems, and permission behavior are unchanged. onItemAddandonItemRemovelet collections persist changes immediately. Both receive the enclosingparentItemfor nested collections, the affecteditem, itsindex, andfieldName; action form helpers can write mutation results (such as a generated ID) back into the row.- A custom
dotsMenucan combine removal (remove: true) with row actions. Custom actions receive the same item context; showing a custom menu does not requireoptions.allowRemove. - In grouped mode, the component renders each configured group and filters items by
groupBy. - Adding an item from a group automatically assigns that group's key to the
groupByfield. - Individual remove soft-deletes rows by default (
removeType: soft), preserving persisted child records for backend reconciliation. SetremoveType: hardfor transient arrays where removed rows should be dropped immediately. - Remove-all clears the full array regardless of
removeType. groupColsmaps to a 12-column Material UI grid (groupCols: 3renders each group atxs: 4).showMoveButtonsis useful on touch devices or dense forms where drag-and-drop is hard to operate.- Stable
_uuidkeys are ignored when detecting primitive wrapper items and are only backfilled for reorder UI collections. - Responsive
groupColsvalues are converted per breakpoint, e.g.{ md: 2 }becomesmd: 6grid width.