Skip to content

Dynamic Form Fields

Problem

Implement dynamic form fields in a production-friendly way with @vielzeug/formit while keeping setup and cleanup explicit.

Runnable Example

The snippet below is copy-paste runnable in a TypeScript project with @vielzeug/formit installed.

Form with dynamically added/removed fields.

typescript
import { createForm } from '@vielzeug/formit';

type TeamMember = {
  name: string;
  email: string;
  role: string;
};

const dynamicForm = createForm({
  defaultValues: {
    teamName: '',
    members: [] as TeamMember[],
  },
  validators: {
    teamName: (v) => (!v ? 'Team name is required' : undefined),
  },
});

// Add a team member
function addMember() {
  const members = dynamicForm.get<TeamMember[]>('members') ?? [];
  dynamicForm.set('members', [...members, { name: '', email: '', role: 'member' }]);
}

// Remove a team member
function removeMember(index: number) {
  const members = dynamicForm.get<TeamMember[]>('members') ?? [];
  dynamicForm.set(
    'members',
    members.filter((_, i) => i !== index),
  );
}

// Update a team member
function updateMember(index: number, field: keyof TeamMember, value: string) {
  const members = dynamicForm.get<TeamMember[]>('members') ?? [];
  const updated = [...members];
  updated[index] = { ...updated[index], [field]: value };
  dynamicForm.set('members', updated);
}

// Submit
async function submitTeam() {
  await dynamicForm.submit(async (values) => {
    const response = await fetch('/api/teams', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(values),
    });
    return response.json();
  });
}

Expected Output

  • The example runs without type errors in a standard TypeScript setup.
  • The main flow produces the behavior described in the recipe title.

Common Pitfalls

  • Forgetting cleanup/dispose calls can leak listeners or stale state.
  • Skipping explicit typing can hide integration issues until runtime.
  • Not handling error branches makes examples harder to adapt safely.