BuzzForm
BuzzFormDocs

Array Field

Repeatable field groups with drag-drop reordering.

Array Field

The array field creates repeatable field groups with add/remove functionality and optional drag-and-drop reordering.

Installation

pnpm dlx shadcn@latest add https://form.buildnbuzz.com/r/array.json

Drag-and-drop requires @dnd-kit. Install with: npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

Usage

import { createSchema } from "@buildnbuzz/buzzform";
import { Form } from "@/components/buzzform/form";

const schema = createSchema([
  {
    type: "array",
    name: "contacts",
    label: "Contacts",
    fields: [
      { type: "text", name: "name", label: "Name", required: true },
      { type: "email", name: "email", label: "Email", required: true },
    ],
  },
]);

// Result: { contacts: [{ name, email }, { name, email }, ...] }

export function ArrayFieldDemo() {
  return <Form schema={schema} onSubmit={console.log} />;
}

Properties

PropTypeDefaultDescription
namestring-Array key in form data
fieldsField[]-Fields for each array item
minRowsnumber-Minimum items
maxRowsnumber-Maximum items

UI Options

OptionTypeDefaultDescription
ui.isSortablebooleantrueEnable drag-drop reordering
ui.addLabelstring"Add Item"Add button text
ui.rowLabelFieldstring-Field name for row titles
ui.collapsedbooleanfalseStart container collapsed
ui.rowsCollapsedbooleanfalseStart rows collapsed
ui.confirmDeletebooleanfalseConfirm before delete all
ui.emptyMessagestring-Empty state message
ui.showErrorBadgebooleantrueShow error count badge

Features

Row Constraints

Limit the number of items:

{
  type: "array",
  name: "items",
  minRows: 1,  // At least 1 item required
  maxRows: 10, // Maximum 10 items
  fields: [...],
}

Dynamic Row Labels

Show a field value as the row title:

{
  type: "array",
  name: "team",
  label: "Team Members",
  fields: [
    { type: "text", name: "name", label: "Name" },
    { type: "email", name: "email", label: "Email" },
  ],
  ui: { rowLabelField: "name" }, // Shows person's name in row header
}

Drag-and-Drop Reordering

Enabled by default. Disable with:

{
  type: "array",
  name: "items",
  fields: [...],
  ui: { isSortable: false },
}

Collapsed Rows

Start with all rows collapsed:

{
  type: "array",
  name: "items",
  fields: [...],
  ui: { rowsCollapsed: true },
}

Delete Confirmation

Require confirmation before deleting all items:

{
  type: "array",
  name: "items",
  fields: [...],
  ui: { confirmDelete: true },
}

Examples

Contact List

{
  type: "array",
  name: "contacts",
  label: "Contacts",
  minRows: 1,
  maxRows: 5,
  fields: [
    {
      type: "row",
      fields: [
        { type: "text", name: "name", label: "Name", required: true },
        { type: "email", name: "email", label: "Email", required: true },
      ],
    },
    { type: "text", name: "phone", label: "Phone" },
  ],
  ui: {
    addLabel: "Add Contact",
    rowLabelField: "name",
    confirmDelete: true,
  },
}

Order Line Items

{
  type: "array",
  name: "items",
  label: "Order Items",
  minRows: 1,
  fields: [
    {
      type: "row",
      fields: [
        { type: "text", name: "product", label: "Product", style: { width: "50%" } },
        { type: "number", name: "quantity", label: "Qty", min: 1, style: { width: "25%" } },
        { type: "number", name: "price", label: "Price", ui: { prefix: "$" }, style: { width: "25%" } },
      ],
    },
  ],
  ui: {
    addLabel: "Add Item",
    rowLabelField: "product",
  },
}

Experience Timeline

{
  type: "array",
  name: "experience",
  label: "Work Experience",
  fields: [
    {
      type: "row",
      fields: [
        { type: "text", name: "company", label: "Company", required: true },
        { type: "text", name: "title", label: "Job Title", required: true },
      ],
    },
    {
      type: "row",
      fields: [
        { type: "date", name: "startDate", label: "Start Date", required: true },
        { type: "date", name: "endDate", label: "End Date" },
      ],
    },
    { type: "textarea", name: "description", label: "Description" },
  ],
  ui: {
    addLabel: "Add Experience",
    rowLabelField: "company",
    isSortable: true,
  },
}

Nested Arrays

{
  type: "array",
  name: "sections",
  label: "Sections",
  fields: [
    { type: "text", name: "title", label: "Section Title" },
    {
      type: "array",
      name: "items",
      label: "Items",
      fields: [
        { type: "text", name: "content", label: "Content" },
      ],
      ui: { addLabel: "Add Item" },
    },
  ],
  ui: { addLabel: "Add Section" },
}

// Result: { sections: [{ title, items: [{ content }, ...] }, ...] }

Read-Only Array

{
  type: "array",
  name: "history",
  label: "Order History",
  fields: [
    { type: "text", name: "orderId", label: "Order ID", readOnly: true },
    { type: "date", name: "date", label: "Date", readOnly: true },
  ],
  ui: { isSortable: false },
  readOnly: true, // No add/remove buttons
}

On this page