Blog>
Snippets

Creating a Dynamic Nested Form with TypeScript and TanStack Form

Show how to create a complex nested form structure, using TypeScript interfaces to type each level of the nested data, demonstrating how to handle arrays and nested objects in forms.
interface NestedFormData {
  user: {
    name: string;
    age: number;
    addresses: {
      street: string;
      city: string;
    }[];
  };
}
Defines the TypeScript interface for the nested form data. This includes a 'user' object with 'name', 'age', and an array of 'addresses', each containing a 'street' and 'city'.
const { useForm, useFieldArray } = require('@tanstack/react-form');

function DynamicNestedForm() {
  const { form, handleSubmit } = useForm<NestedFormData>({ 
    defaultValues: {
      user: {
        name: '',
        age: 0,
        addresses: [{ street: '', city: '' }]
      }
    }
  });

  const { fields, append, remove } = useFieldArray({
    form,
    name: 'user.addresses'
  });

  // Form submission logic
  const onSubmit = async (values: NestedFormData) => {
    console.log('Form Data:', values);
  };

  return (
    // Form rendering logic using fields for dynamic address fields
  );
}
Sets up the dynamic nested form using TanStack Form's useForm and useFieldArray hooks. Initial values are set for the user and their addresses. 'append' and 'remove' are used to dynamically add or remove address fields.
// Example of rendering logic within DynamicNestedForm's return statement
<form onSubmit={handleSubmit(onSubmit)}>
  <input {...form.register('user.name')} placeholder='Name' />
  <input {...form.register('user.age')} placeholder='Age' type='number' />
  {fields.map((field, index) => (
    <div key={field.id}>
      <input {...form.register(`user.addresses.${index}.street`)} placeholder='Street' />
      <input {...form.register(`user.addresses.${index}.city`)} placeholder='City' />
      <button type='button' onClick={() => remove(index)}>Remove Address</button>
    </div>
  ))}
  <button type='button' onClick={() => append({ street: '', city: '' })}>Add Address</button>
  <button type='submit'>Submit</button>
</form>
Illustrates how the form and dynamic address fields are rendered and managed. Users can add or remove address entries, and submit the whole form, which includes nested and array data structures.