FIELD GROUP REPEAT: "Add another" repeating group of related form fields
COMPOSES: <fieldset>/<legend> | .form-control / .form-select / .form-label / .form-text | .btn-tertiary | .btn-sm .btn-danger / .btn-tertiary
Use wherever an applicant repeats the same small set of fields for multiple people or
items — e.g. one fieldset per child on a multi-child application. Each item is numbered
("Child 1", "Child 2"…) and can be removed down to a minimum of 1. Removing an item with
unsaved changes asks for confirmation inline first; removing a clean (untouched) item
removes it immediately. field_group_repeat_controller.js owns cloning,
renumbering, the dirty check, and screen-reader announcements.
Starts at 1 item, max 4. Click Add another child to append a
new fieldset — legends renumber and every field's name/id/for
stays uniquely indexed. Fill in a field then click a Remove button: because the
item is now dirty, an inline confirm row replaces the trigger (Escape or Cancel backs
out). An untouched item removes immediately, no confirm. With only 1 item left, its
Remove button disables — at least one child is required. Add a 4th item and the
Add another child button disables at the max.
Maximum of 4 children reached.
<div data-controller="field-group-repeat" data-field-group-repeat-max-value="4" data-field-group-repeat-label-value="Child"><div class="field-group-repeat" data-field-group-repeat-target="container"><fieldset class="field-group-repeat-item" data-field-group-repeat-target="item" data-index="1"><legend class="tw:sr-only">Child 1</legend><div class="field-group-repeat-header"><span class="field-group-repeat-legend" aria-hidden="true">Child 1</span><button class="field-group-repeat-remove" …>Remove</button><div class="field-group-repeat-confirm" hidden>…</div></div>…fields…</fieldset></div><button class="btn btn-tertiary field-group-repeat-add" data-field-group-repeat-target="add">Add another child</button><template data-field-group-repeat-target="template">…</template></div>
At the max value: the Add another child trigger gets the real
disabled attribute (kept visible and explainable rather than hidden) and a
.form-text hint appears underneath. All four legends are numbered in order;
removing any of them (e.g. "Child 2") renumbers the remaining three and re-enables the
add button.
Maximum of 4 children reached.
<button class="btn btn-tertiary field-group-repeat-add" data-field-group-repeat-target="add" disabled>Add another child</button><p class="form-text" data-field-group-repeat-target="maxHint">Maximum of 4 children reached.</p>