Arrays
String arrays and object arrays with dynamic controls
Form Wire supports two types of array fields: string arrays and object arrays.
String Arrays
const schema = z.object({
tags: z.string().min(1).array().min(1),
});Renders as a dynamic list of text inputs with:
- Add button to append a new empty input
- Remove button per item
- Move up / Move down buttons per item
Configure labels:
fields: {
tags: {
label: "Tags",
array: {
addLabel: "Add tag",
removeLabel: "Remove",
moveUpLabel: "Up",
moveDownLabel: "Down",
itemLabel: "Tag",
},
},
}itemLabel can be a string or a function:
itemLabel: (index) => `Tag ${index + 1}`Object Arrays
const schema = z.object({
users: z.object({
name: z.string().min(1),
email: z.email(),
}).array(),
});Each item renders as a <fieldset> with all its nested fields. The same add/remove/reorder controls apply.
Configure per-item fields in the schema — they use the same config system as top-level fields.
Nested Object Arrays
const schema = z.object({
team: z.object({
name: z.string(),
users: z.object({
name: z.string(),
email: z.email(),
}).array(),
}),
});Nested arrays work identically — they render inside their parent fieldset group.
Read-Only and Disabled Arrays
When an array field is read-only or disabled, the add/remove/reorder controls are hidden automatically.
Array Field Values
Array values are submitted as repeated form entries with the same name:
<input name="tags" value="react" />
<input name="tags" value="zod" />Form Wire parses these back into a string[] automatically.
Object Array Naming
Object array items use bracket-style naming:
<input name="users[0].name" value="Ada" />
<input name="users[0].email" value="ada@form.dev" />
<input name="users[1].name" value="Grace" />Form Wire handles the serialization and parsing transparently.