Skip to main content

Nested fields

Real-world forms are rarely flat. They usually contain objects, groups, and nested data structures.

Formora supports nested fields out of the box by treating field names as paths.

There is no special API for nested data — the same useForm and register calls work at any depth.


Field names as paths

In Formora, a field name is a path into your values object.

Examples:

email
profile.name
profile.address.street
items.0.name

Formora automatically reads and writes values at the correct depth.


Basic nested object example

import { useForm } from "formora";

type Values = {
profile: {
name: string;
address: {
street: string;
city: string;
};
};
};

const form = useForm<Values>({
initialValues: {
profile: {
name: "",
address: {
street: "",
city: "",
},
},
},
validateOn: "blur",
});

Register nested fields using dot notation:

<input {...form.register("profile.name")} />
<input {...form.register("profile.address.street")} />
<input {...form.register("profile.address.city")} />

Validation for nested fields

Validation rules work exactly the same as for flat fields.

<input
{...form.register("profile.address.street", {
required: "Street is required",
})}
/>

Errors are stored at the same nested path:

{
profile: {
address: {
street: "Street is required",
},
},
}

Access errors safely using optional chaining:

{
form.errors.profile?.address?.street && (
<p>{String(form.errors.profile.address.street)}</p>
);
}

Error visibility

Formora separates validation from error visibility.

  • errors tells you what is invalid
  • touched / dirty tell you how the user interacted

You decide when to show errors.

Common pattern (show after blur)

<input
{...form.register("profile.address.street", {
required: "Street is required",
})}
/>;

{
form.touched?.profile?.address?.street &&
form.errors?.profile?.address?.street && (
<p>{String(form.errors.profile.address.street)}</p>
);
}

Nested fields with arrays

Paths can include array indices at any level:

users.0.profile.email
orders.2.items.1.name

Formora treats these as normal paths.

info

This guide only covers path-based access. Field array helpers (add/remove/reorder) are documented separately once stabilized.


Resetting nested fields

Formora currently exposes a form-level reset only.

form.reset();

This resets:

  • all values back to initialValues
  • all errors
  • all touched and dirty state

To reset part of a form, update initialValues and call reset().


Common mistakes to avoid

warning

Do not mix local React state with Formora state for the same fields.

Always read values and errors from form.values and form.errors using paths.


Summary

  • Nested fields are handled via path-based names
  • The same register API works at any depth
  • Validation and meta state follow the same nested structure
  • Error visibility is controlled by your UI logic

Formora lets you model form data exactly as your backend expects.