Guides
Nested Objects
Group fields into nested objects with fieldsets
Zod nested objects produce dotted field names and semantic <fieldset> groups.
Basic Nesting
const schema = z.object({
profile: z.object({
firstName: z.string().min(1),
lastName: z.string().min(1),
}),
contact: z.object({
email: z.email(),
}),
});This produces fields named profile.firstName, profile.lastName, and contact.email.
Configure them with dotted keys:
createFormWire(schema, {
fields: {
"profile.firstName": { label: "First name", placeholder: "Ada" },
"profile.lastName": { label: "Last name", placeholder: "Lovelace" },
"contact.email": { label: "Email", placeholder: "ada@form.dev" },
},
});Rendering
When auto-rendered, nested objects produce <fieldset> groups:
<fieldset>
<legend>Profile</legend>
<input name="profile.firstName" />
<input name="profile.lastName" />
</fieldset>
<fieldset>
<legend>Contact</legend>
<input name="contact.email" />
</fieldset>Default Values
Nest default values to match the schema shape:
<Form
action={submit}
defaultValues={{
profile: { firstName: "Ada", lastName: "Lovelace" },
contact: { email: "ada@form.dev" },
}}
/>Deep Nesting
You can nest objects multiple levels deep. Each level produces its own fieldset group and dotted field path.
Discriminated Unions
Zod discriminated unions are also supported:
z.discriminatedUnion("type", [
z.object({ type: z.literal("personal"), name: z.string() }),
z.object({ type: z.literal("business"), company: z.string() }),
]);Form Wire shows only the fields that belong to the active discriminator value.