---
title: Form
description: Display fields that submit data to a Backlit action.
---

A form block collects data and submits it to one resource action. The action owns the
validation schema. The schema also gives the form its input type, so TypeScript
checks field names and initial-value keys.

Use any Standard Schema validator for the action. These examples use Zod.

## API

```ts
form(action: ActionDefinition): FormBuilder
```

| Method            | Input                          | Result                                             |
| ----------------- | ------------------------------ | -------------------------------------------------- |
| `fields`          | `...FieldBuilderContract[]`    | Creates one block of fields that submit together.  |
| `setContent`      | `Producer[]`                   | Sets the blocks inside the form.                   |
| `withInitialData` | `FormInitialData<ActionInput>` | Sets the values that the form shows first.         |
| `setSubmitAction` | `{ label: string }`            | Configures the submit action.                      |
| `setClearAction`  | `{ label: string }`            | Adds and configures the clear action.              |
| `onDefect`        | `(defect: Defect) => void`     | Handles an initial value that cannot be converted. |

`form.fields` returns a `FormFieldsBuilder`. Call `peers(...sets)` on this
builder to place related fields on the same line. A field not in a peer set
stands alone.

Calling `setContent`, `withInitialData`, `setSubmitAction`, or `setClearAction`
again replaces the previous value.

## Basic form

Create the form from its target action. Then add a field block to its content.
The protocol target uses the resource and action names.

<BacklitExample path="form/basic" view="create" />

## Content composition

A form can contain the same blocks as a view. Place field blocks in panels or
sections when the inputs need visible groups.

<BacklitExample path="form/content" view="create" />

## Initial values

Use `withInitialData` for edit data or create-form defaults. Backlit converts each
value to the wire type of its displayed field. A key without a displayed field
passes through without conversion.

<BacklitExample path="form/initial_values" view="edit" />

## Submit label

Use `setSubmitAction` to replace the renderer's default submit label.

<BacklitExample path="form/submit_label" view="create" />

## Clear label

Use `setClearAction` to add a control that restores the initial values in the client.
Clearing a form does not send a request.

<BacklitExample path="form/clear_label" view="create" />

## Global remapper

Use `remappers.registerRemappers` when source data needs a different conversion.
Register it for the `input` role. The change applies to all forms. A form does
not accept local remapper overrides.

<BacklitExample path="form/custom_remapper" view="edit" />

## Defect reporter

Use `onDefect` to report an initial value that a remapper cannot convert. The
invalid key is not included in the protocol output. The default reporter writes
a warning to the console.

<BacklitExample path="form/defect_reporter" view="edit" />

## Form inside a zone

A zone can produce a form when the form must refresh independently from the
other view content.

<BacklitExample path="form/zone" view="edit" />

## All options

This example uses peer fields, composed content, initial values, both control
labels, and a defect reporter in one form.

<BacklitExample path="form/all_options" view="edit" />

See [Form fields](/reference/forms/form-fields) for field ordering and peer
placement.

## Conditions and repeated rows

Use `when`, `ref`, `all`, `any`, and `none` to create typed form conditions.
Use `repeater` for arrays of objects. See [Conditions](/reference/forms/conditions)
and [Repeaters](/reference/forms/repeater).

A regular form cannot contain another form. Put a small action form in an
[Action target](/reference/targets/action). Form targets use the current view's
arguments, so a form view and its action must use compatible parameter order.
The initial-data keys are checked against the schema. Values can be raw input
for the remappers; they are not restricted to already converted schema values.
