or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

field-registration.mdform-actions.mdform-creation.mdindex.mdstate-management.mdutilities.mdvalidation.md
tile.json

form-creation.mddocs/

Form Creation

Core form creation functionality for initializing form instances with comprehensive configuration and lifecycle management capabilities.

Capabilities

Create Form

Creates a new form instance with the specified configuration.

/**
 * Creates a new form instance with the specified configuration
 * @param config - Form configuration object
 * @returns FormApi instance for interacting with the form
 */
function createForm<
  FormValues = Record<string, any>,
  InitialFormValues extends Partial<FormValues> = Partial<FormValues>
>(config: Config<FormValues, InitialFormValues>): FormApi<FormValues, InitialFormValues>;

Usage Example:

import { createForm } from "final-form";

const form = createForm({
  onSubmit: async (values) => {
    // Handle form submission
    const response = await fetch('/api/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(values)
    });
    
    if (!response.ok) {
      // Return submission errors
      return { email: 'Email already exists' };
    }
  },
  initialValues: {
    firstName: '',
    lastName: '',
    email: ''
  },
  validate: (values) => {
    const errors = {};
    if (!values.email) {
      errors.email = 'Required';
    }
    return errors;
  }
});

Configuration Interface

Complete configuration options for form creation.

interface Config<
  FormValues = Record<string, any>,
  InitialFormValues extends Partial<FormValues> = Partial<FormValues>
> {
  /** Required submission handler function */
  onSubmit: (
    values: FormValues,
    form: FormApi<FormValues, InitialFormValues>,
    callback?: (errors?: SubmissionErrors) => void
  ) => SubmissionErrors | Promise<SubmissionErrors> | void;
  
  /** Optional debug callback for form state changes */
  debug?: DebugFunction<FormValues, InitialFormValues>;
  
  /** Whether to destroy field state when field is unregistered (default: false) */
  destroyOnUnregister?: boolean;
  
  /** Initial values for form fields */
  initialValues?: InitialFormValues;
  
  /** Keep dirty state when form is reinitialized (default: false) */
  keepDirtyOnReinitialize?: boolean;
  
  /** Custom mutator functions for advanced form state manipulation */
  mutators?: { [key: string]: Mutator<FormValues, InitialFormValues> };
  
  /** Form-level validation function */
  validate?: (values: FormValues) => ValidationErrors | Promise<ValidationErrors>;
  
  /** Whether to validate fields on blur (default: false) */
  validateOnBlur?: boolean;
  
  /** Custom callback scheduler for controlling when callbacks are executed */
  callbackScheduler?: (callback: () => void) => void;
}

Configuration Examples:

// Basic form with validation
const basicForm = createForm({
  onSubmit: (values) => console.log(values),
  validate: (values) => {
    const errors = {};
    if (!values.name?.trim()) {
      errors.name = 'Name is required';
    }
    if (values.age && values.age < 18) {
      errors.age = 'Must be 18 or older';
    }
    return errors;
  }
});

// Form with async validation
const asyncForm = createForm({
  onSubmit: async (values) => {
    await submitToAPI(values);
  },
  validate: async (values) => {
    if (values.username) {
      const available = await checkUsernameAvailability(values.username);
      if (!available) {
        return { username: 'Username already taken' };
      }
    }
  }
});

// Form with custom mutators
const mutatorForm = createForm({
  onSubmit: (values) => console.log(values),
  mutators: {
    setValue: (args, state, tools) => {
      const [field, value] = args;
      tools.changeValue(state, field, () => value);
    },
    clearAll: (args, state, tools) => {
      const registeredFields = Object.keys(state.fields);
      registeredFields.forEach(field => {
        tools.changeValue(state, field, () => undefined);
      });
    }
  }
});

Configuration Options

Available configuration option keys for runtime form configuration.

const configOptions: ConfigKey[];

type ConfigKey = 
  | "debug"
  | "destroyOnUnregister"
  | "initialValues"
  | "keepDirtyOnReinitialize"
  | "mutators"
  | "onSubmit"
  | "validate"
  | "validateOnBlur"
  | "callbackScheduler";

Debug Function Type

Type definition for debug callback functions.

type DebugFunction<
  FormValues = Record<string, any>,
  InitialFormValues extends Partial<FormValues> = Partial<FormValues>
> = (
  state: FormState<FormValues, InitialFormValues>,
  fieldStates: { [key: string]: FieldState<any> }
) => void;

Debug Usage Example:

const form = createForm({
  onSubmit: (values) => console.log(values),
  debug: (formState, fieldStates) => {
    console.log('Form State:', formState);
    console.log('Field States:', fieldStates);
  }
});

Mutator Function Type

Type definition for custom mutator functions that can modify form state.

type Mutator<
  FormValues = Record<string, any>,
  InitialFormValues extends Partial<FormValues> = Partial<FormValues>
> = (
  args: any[],
  state: MutableState<FormValues, InitialFormValues>,
  tools: Tools<FormValues, InitialFormValues>
) => any;

interface Tools<FormValues, InitialFormValues> {
  changeValue: ChangeValue<FormValues, InitialFormValues>;
  getIn: GetIn;
  renameField: RenameField<FormValues, InitialFormValues>;
  resetFieldState: (name: string) => void;
  setIn: SetIn;
  shallowEqual: IsEqual;
}

Mutator Usage Example:

const form = createForm({
  onSubmit: (values) => console.log(values),
  mutators: {
    // Custom mutator to set multiple fields at once
    setFields: (args, state, tools) => {
      const [fieldsObject] = args;
      Object.keys(fieldsObject).forEach(fieldName => {
        tools.changeValue(state, fieldName, () => fieldsObject[fieldName]);
      });
    },
    // Custom mutator to increment a numeric field
    increment: (args, state, tools) => {
      const [fieldName, amount = 1] = args;
      tools.changeValue(state, fieldName, (value) => (value || 0) + amount);
    }
  }
});

// Use the custom mutators
form.mutators.setFields({ firstName: 'John', lastName: 'Doe' });
form.mutators.increment('counter', 5);