Guides / Nested object and Array

Nested object and Array

Conform support both nested object and array by leveraging a naming convention on the name attribute.

#Naming Convention

Conform uses the object.property and array[index] syntax to denote data structure. These notations could be combined for nested array as well. e.g. tasks[0].content. If the form data has an entry ['tasks[0].content', 'Hello World'], the object constructed will become { tasks: [{ content: 'Hello World' }] }.

However, there is no need to set the name attribute of each field manually. Conform will always infer the name for you and you will have better type safety if you are using the generated name.

#Nested Object

To set up a nested field, just call the getFieldset() method from the parent field metadata to get access to each child field with name infered automatically.

1import { useForm } from '@conform-to/react';
2
3function Example() {
4  const [form, fields] = useForm();
5  const address = fields.address.getFieldset();
6
7  return (
8    <form id={form.id}>
9      {/* Set the name to `address.street`, `address.zipcode` etc. */}
10      <input name={address.street.name} />
11      <div>{address.street.errors}</div>
12      <input name={address.zipcode.name} />
13      <div>{address.zipcode.errors}</div>
14      <input name={address.city.name} />
15      <div>{address.city.errors}</div>
16      <input name={address.country.name} />
17      <div>{address.country.errors}</div>
18    </form>
19  );
20}

#Array

When you need to setup a list of fields, you can call the getFieldList() method from the parent field metadata to get access to each item field with name infered automatically as well. If you want to modify the items in the list, you can also use the insert, remove and reorder intents as explained in the Intent button page.

1import { useForm } from '@conform-to/react';
2
3function Example() {
4  const [form, fields] = useForm();
5  const tasks = fields.tasks.getFieldList();
6
7  return (
8    <form id={form.id}>
9      <ul>
10        {tasks.map((task) => (
11          <li key={task.key}>
12            {/* Set the name to `task[0]`, `tasks[1]` etc */}
13            <input name={task.name} />
14            <div>{task.errors}</div>
15          </li>
16        ))}
17      </ul>
18    </form>
19  );
20}

#Nested Array

You can also combine both getFieldset() and getFieldList() for nested array.

1import { useForm } from '@conform-to/react';
2
3function Example() {
4  const [form, fields] = useForm();
5  const todos = fields.todos.getFieldList();
6
7  return (
8    <form id={form.id}>
9      <ul>
10        {todos.map((todo) => {
11          const todoFields = todo.getFieldset();
12
13          return (
14            <li key={todo.key}>
15              <input name={todoFields.title.name} />
16              <div>{todoFields.title.errors}</div>
17              <input name={todoFields.notes.name} />
18              <div>{todoFields.notes.errors}</div>
19            </li>
20          );
21        })}
22      </ul>
23    </form>
24  );
25}