Repeater Field
The repeater field type renders a dynamic list of sub-field rows β for line items, team members, addresses, and similar one-to-many data.
Live Demoβ
- Preview
- Code
Team Members
1
import { RavenForm } from "raven-form-engine";
import type { FormSchema } from "raven-form-engine";
const schema: FormSchema = {
fields: [
{
name: "teamMembers",
type: "repeater",
label: "Team Members",
colSpan: 12,
repeaterConfig: {
minRows: 1,
maxRows: 5,
addLabel: "+ Add Member",
removeLabel: "X",
defaultRow: { name: "", email: "", role: "viewer" },
fields: [
{ name: "name", type: "text", label: "Full Name", colSpan: 4 },
{ name: "email", type: "email", label: "Email", colSpan: 4 },
{
name: "role",
type: "select",
label: "Role",
colSpan: 4,
options: [
{ label: "Admin", value: "admin" },
{ label: "Editor", value: "editor" },
{ label: "Viewer", value: "viewer" },
],
},
],
},
},
],
};
export function TeamForm() {
return (
<RavenForm
schema={schema}
onSubmit={(values) => console.log(values.teamMembers)}
/>
);
}
RepeaterConfigβ
interface RepeaterConfig {
fields: FormField[]; // sub-fields per row
minRows?: number; // minimum rows (default: 0)
maxRows?: number; // maximum rows allowed
addLabel?: string; // label for the add-row button
removeLabel?: string; // label/icon for the remove-row button
defaultRow?: Record<string, unknown>; // default values for new rows
}
Submitted Value Shapeβ
The repeater stores an array of row objects:
{
"teamMembers": [
{ "name": "Alice", "email": "alice@example.com", "role": "admin" },
{ "name": "Bob", "email": "bob@example.com", "role": "editor" }
]
}
Invoice Line Items Exampleβ
- Preview
- Code
Invoice Line Items
1
{
name: 'lineItems',
type: 'repeater',
label: 'Line Items',
colSpan: 12,
repeaterConfig: {
minRows: 1,
maxRows: 10,
fields: [
{ name: 'description', type: 'text', label: 'Description', colSpan: 6 },
{ name: 'qty', type: 'number', label: 'Qty', colSpan: 2, defaultValue: 1 },
{ name: 'unitPrice', type: 'number', label: 'Unit Price', colSpan: 2 },
],
},
}