Form Wire
Guides

Field Types

All supported field types and how to configure them

Form Wire maps Zod types to form controls automatically. Here's every supported type.

Text Input

z.string().min(1, "Required")

Renders as <input type="text">. Override with the component option:

fields: {
  bio: { label: "Bio", component: "textarea" },
}

Email

z.email("Enter a valid email")

Renders as <input type="email">.

Number

z.coerce.number().min(18, "Must be 18+")

Renders as <input type="number">. Uses z.coerce so string form values are coerced to numbers.

Date

z.coerce.date()

Renders as <input type="date">.

Boolean / Checkbox

z.boolean()

Renders as <input type="checkbox">.

For "must accept" patterns:

z.literal(true, "You must accept the terms")

This renders a checkbox that must be checked to submit.

Select

z.enum(["pending", "active", "paused"])

Renders as <select> with options. Optional selects include a blank placeholder option.

Configure the placeholder:

fields: {
  status: { label: "Status", placeholder: "Choose a status" },
}

File

z.file()

Renders as <input type="file">.

String Arrays

z.string().array().min(1)

Renders as a dynamic list of text inputs with add/remove/reorder controls.

Configure labels:

fields: {
  tags: {
    label: "Tags",
    array: {
      addLabel: "Add tag",
      removeLabel: "Remove",
      itemLabel: "Tag",
    },
  },
}

Object Arrays

z.object({
  name: z.string(),
  email: z.email(),
}).array()

Renders as fieldset groups with add/remove/reorder controls for each item.

Custom Component Override

Use component in field config to override the default rendering:

fields: {
  bio: { component: "textarea" },
}

Currently supported: "textarea". For full custom rendering, use a custom mapper.

On this page