Core form creation functionality for initializing form instances with comprehensive configuration and lifecycle management capabilities.
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;
}
});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);
});
}
}
});Available configuration option keys for runtime form configuration.
const configOptions: ConfigKey[];
type ConfigKey =
| "debug"
| "destroyOnUnregister"
| "initialValues"
| "keepDirtyOnReinitialize"
| "mutators"
| "onSubmit"
| "validate"
| "validateOnBlur"
| "callbackScheduler";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);
}
});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);