Skip to main content
Menu
On this page

Repeating group

Let a respondent add several instances of the same small set of fields, like guests or line items.

Rendered by the SDK
@usefillo/react

Guest 1 of 1

Interactive local preview. Nothing is submitted.

The repeating group field renders a small template of fields as a card, and lets the respondent add or remove instances of it — a guest list, order line items, or any "one row per thing" question. Each instance stores its own answers for every field in the template.

Options

OptionTypeDefaultBehavior
fieldsField[]requiredThe repeated template, up to 12 fields
maxInstancesnumberrequiredUpper bound on instances, 1 through 20
minInstancesnumber1Lower bound, 0 through maxInstances
addLabelstring"Add another"Label on the add-instance button
itemLabelstringthe field's labelNames one instance — headings, announcements, and export columns

maxInstances is required and bounded (1–20) so a form can never grow unbounded mid-fill; an out-of-range minInstances or maxInstances is a schema error, not a silent clamp. The container's own required is always falseminInstances alone governs whether the field needs an answer, the same way hidden and calculated fields are never required.

Value shape

A repeating group stores an array of objects, one per instance, each one keyed by child field ID:

ts
data.guests = [
  { name: "Ada Lovelace", email: "ada@example.com" },
  { name: "Grace Hopper", email: "grace@example.com" },
];

A child's value uses the exact same shape a top-level field of that kind would store. An absent key means zero instances — unanswered only when minInstances is 0. Instances keep the order the respondent added them in; there is no respondent-facing reordering.

Template fields

Template fields are drawn from a restricted set: short_text, long_text, email, url, phone, number, select, multi_select, dropdown, checkbox, date, rating, and linear_scale. A nested repeating_group, calculated, file_upload, signature, matrix, ranking, hidden, or custom child is a schema error — each is more instance-plumbing than a v1 group takes on.

A child's visibleIf may reference only another field in the same group, evaluated per instance over that instance's own answers. Nothing outside the group can reference a child field, and a child can't reference anything outside the group — both directions are schema errors, so a group's logic never depends on (or leaks into) the rest of the form.

Validation

An instance count outside minInstancesmaxInstances is a real validation error in both directions on submit — unlike a calculated field, the count is respondent input (a group with minInstances: 2, maxInstances: 3 rejects one instance with "Add at least 2 entries" and rejects a fifth with "At most 3 entries"). Each child is validated per instance with the same rules a top-level field of that kind uses. A failing child's error is keyed ${groupId}.${index}.${childId}guests.0.email names the first instance's email child when the group's id is guests — dot-safe everywhere a plain field id is (DOM ids, aria-describedby, the client errors map), and it's the documented way to address one instance's field from outside a renderer. A key inside a submitted instance that doesn't match any child id is dropped silently rather than rejected, the same convention an unrecognized top-level field id already follows.

Add a repeating group

In the dashboard, select Add block, choose Repeating group, then add child fields to the template the same way you would to a page, and set the instance bounds.

In code:

ts
const guests = {
  id: "guests",
  kind: "repeating_group",
  label: "Guests",
  itemLabel: "Guest",
  minInstances: 1,
  maxInstances: 6,
  fields: [
    { id: "name", kind: "short_text", label: "Name", required: true },
    { id: "email", kind: "email", label: "Email" },
  ],
} as const;

With JSX (React), the template is written as ordinary field children — the one place a <Fillo.*> element nests other field elements instead of configuring them through props:

tsx
<Fillo.RepeatingGroup id="guests" label="Guests" itemLabel="Guest" minInstances={1} maxInstances={6}>
  <Fillo.Text id="name" label="Name" required />
  <Fillo.Email id="email" label="Email" />
</Fillo.RepeatingGroup>

Only field elements are allowed as children — a <Fillo.Page>, <Fillo.Option>, or content block there is a compile-time error, the same fail-loud rule as an unsupported child kind.

Where instances show up

The responses grid shows one summary cell per response ("3 × Guest: Ada, Grace, Alan"); opening the response shows every instance in full, each one its own "Guest n" card. CSV export writes wide, deterministic columns — maxInstances times the number of child fields, headed "Guest 1 — Name", "Guest 1 — Email", "Guest 2 — Name", and so on, from the schema rather than from any one response, so the header never shifts between rows. Webhooks, the API, and Zapier carry the raw instance array in answers and the same one-line summary in formatted. Google Sheets and Notion carry that same one-line summary text in v1 — a dedicated child record per instance (a second Sheets tab, a linked Notion database) is a deliberate later step, not part of this release.

SDK compatibility

A form containing a repeating group serves a raised minimum SDK version (0.13.0) from the public form endpoint. An older SDK doesn't recognize the repeating_group kind and would drop the whole field silently, so it fails fast with an update message instead of rendering an incomplete form.

  • Conditional logic: How a child field's visibleIf is scoped to its own group.
  • Schema and validation: Instance-count and per-child validation rules.
  • Matrix: A different repeat shape — the same rows against one shared set of columns.

Updated

Was this page helpful?