Array Field
Repeatable fields for dynamic lists of items.
Array Field
The array field renders repeatable fields for dynamic lists.
Schema Properties
Prop
Type
UI Options
| Option | Type | Default | Description |
|---|---|---|---|
variant | "default" | "minimal" | "default" | Visual style for the container |
rowLabel | unknown | "Item #N" | Row header label (supports $data) |
isSortable | boolean | true | Enable drag-to-reorder |
showErrorBadge | boolean | true | Show error-count badge in header |
allowDuplicate | boolean | false | Show a duplicate button per row |
confirmDelete | boolean | true | Require confirmation before delete all |
labels | object | - | Text and label overrides |
labels.add | ReactNode | "Add Item" | Label for the add button |
labels.empty | ReactNode | "No items added yet." | Message shown when no items exist |
labels.rowFallback | string | "Item #N" | Fallback when rowLabel is empty |
React Overrides: The label, description, ui.labels.add, and ui.labels.empty properties all support ReactNode (JSX) when importing defineSchema from @buildnbuzz/form-react.
Basic Usage
const schema = defineSchema({
fields: [
{
type: "array",
name: "contacts",
label: "Contacts",
minItems: 1,
maxItems: 5,
fields: [
{ type: "text", name: "name", label: "Name" },
{ type: "email", name: "email", label: "Email" },
],
},
],
});
// Result: { contacts: Array<{ name: string, email: string }> }Examples
With Row Label
{
type: "array",
name: "teamMembers",
label: "Team Members",
rowLabel: { $data: "/name" }, // Shows name in row header
fields: [
{ type: "text", name: "name", label: "Name" },
{ type: "text", name: "role", label: "Role" },
],
}With Custom Labels
{
type: "array",
name: "projects",
label: "Projects",
ui: {
labels: {
add: "Add Project",
empty: "No projects added yet",
},
isSortable: true,
allowDuplicate: true,
confirmDelete: true,
},
minItems: 1,
maxItems: 10,
fields: [
{ type: "text", name: "name", label: "Project Name" },
{ type: "text", name: "description", label: "Description" },
],
}Disable Sorting
{
type: "array",
name: "steps",
label: "Steps",
ui: { isSortable: false },
fields: [
{ type: "text", name: "step", label: "Step" },
],
}Minimal VariantW
{
type: "array",
name: "socialLinks",
label: "Social links",
primitive: true,
ui: { variant: "minimal" },
fields: [{ type: "text", placeholder: "https://..." }],
}With Error Badge
{
type: "array",
name: "items",
label: "Items",
ui: { showErrorBadge: true },
fields: [
{ type: "text", name: "name", label: "Name", required: true },
],
}Data Shape
Array fields do contribute to form data as arrays:
// Schema
{
type: "array",
name: "contacts",
fields: [
{ type: "text", name: "name" },
{ type: "email", name: "email" },
],
}
// Result type: { contacts: Array<{ name: string, email: string }> }Primitive Arrays
Use primitive: true for arrays of single values. Omit the item name to map the item value directly into the array. This is perfect for simple lists of strings, numbers, or dates.
// Schema
{
type: "array",
name: "tags",
primitive: true,
fields: [
{ type: "text" } // Name is omitted
],
}
// Result type: { tags: string[] }Use primitive: true for arrays of single values. By default, this creates a flat array (e.g., string[]). However, if you provide a name for the item field, each item will be wrapped in an object:
// Choice 1: Flat Array (no item name)
{
type: "array",
name: "tags",
primitive: true,
fields: [{ type: "text" }],
}
// Result type: { tags: string[] }
// Choice 2: Object Array (with item name)
{
type: "array",
name: "socials",
primitive: true,
fields: [{ type: "text", name: "url" }],
}
// Result type: { socials: Array<{ url: string }> }Auto-Derived Validators
| Property | Validator |
|---|---|
minItems | minItems |
maxItems | maxItems |
Row Label with Dynamic Values
Use { $data: "fieldName" } to display a field value from each row:
{
type: "array",
name: "users",
label: "Users",
rowLabel: { $data: "/username" }, // Shows username in header
fields: [
{ type: "text", name: "username", label: "Username" },
{ type: "email", name: "email", label: "Email" },
],
}For primitive arrays, use { $data: "/" } to reference the current item value:
{
type: "array",
name: "tags",
primitive: true,
rowLabel: { $data: "/" },
fields: [{ type: "text" }],
}