Complex Forms

What are Complex Forms?

Complex forms would typically contain data in a structure that is more than just simple key/value pairs. For example, a list of people who each have their own email, phone and street address. This would essentially be an array of objects.

Input naming

Objects

Nested items can be created by separating the items with . (dot) in the name. For example, person.name would be converted to { person: { name: 'sam' } }.

Arrays

Arrays, either top level or nested are created by specifying the zero-based index in the name. For example person.pets.0 would be converted to { person: { pets: [ 'cat' ] } }.

Example

The key to creating a complex form is in the naming of the inputs. Below would be an example of the list described above:

<form>
  <input name="person.0.name" value="Sam">
  <input name="person.0.email" value="sam@complexform.com">
  <input name="person.0.pets.0" value="cat">
  <input name="person.0.pets.1" value="dog">
  <input name="person.0.address.street" value="1234 Example Ave.">
  <input name="person.0.address.city" value="Qwik">
  <input name="person.0.address.state" value="IA">
  <input name="person.0.address.zip" value="00000">
  <input name="person.0.pets.0" value="beaver">
 
  <input name="person.1.name" value="Bonnie">
  <input name="person.1.email" value="bonnie@hishai.net">
  <input name="person.1.address.street" value="768 Resolution Way">
  <input name="person.1.address.city" value="Jaffa">
  <input name="person.1.address.state" value="IL">
  <input name="person.1.address.zip" value="01948">
</form>

Output object

The after submitting the form the data would be parsed in an object like this:

{
  "person": [
    {
      "name": "Sam",
      "email": "sam@complexform.com",
      "address": {
        "street": "1234 Example Ave.",
        "city": "Qwik",
        "state": "IA",
        "zip": "00000"
      },
      "pets": ["beaver"]
    },
    {
      "name": "Bonnie",
      "email": "bonnie@hishai.net",
      "address": {
        "street": "768 Resolution Way",
        "city": "Jaffa",
        "state": "IL",
        "zip": "01948"
      }
    }
  ]
}

Using with Actions

Complex forms can be validated using zod$ with routeAction$ and globalAction$. Continuing with the previous examples it would look like this:

export const action = routeAction$(
  async (person) => {
    return { success: true, person, };
  },
  // Zod schema is used to validate the FormData
  zod$({
    person: z.array(
      z.object({
        name: z.string(),
        email: z.string().email(),
        address: z.object({
          street: z.string(),
          city: z.string(),
          state: z.string(),
          zip: z.coerce.number()
        }),
        pets: z.array(z.string())
      })
    ),
  })
);

Contributors

Thanks to all the contributors who have helped make this documentation better!

  • ulic75
  • hamatoyogi
  • aendel