Manage the values, errors and submit of a form, and bind them to Bolio UI fields with getInputProps.
This is custom React hooks, you need to follow the Basic Rules when you use it.
Errors show on submit and clear as the user fixes each field.
Use dot paths for nested objects and list items, such as user.email or tags.0.label. Errors use the same flat keys. A rule object under a list key runs for every item.
const form = useForm({
initialValues: { user: { email: '' }, tags: [{ label: '' }] },
validate: {
user: { email: isEmail('Enter a valid email') },
tags: { label: isNotEmpty('Enter a tag') }
}
})
form.getInputProps('tags.0.label')
form.insertListItem('tags', { label: '' })
form.removeListItem('tags', 0)
Rules run on submit or when you call validate(). Pass validateInputOnChange or validateInputOnBlur as true, or as a list of paths, to validate while the user fills the form. Without them, an error clears as soon as its field changes.
A rule is a function that receives the field value, all values and the path, and returns the error message or null. validate also accepts one function that returns all errors at once.
const form = useForm({
initialValues: { password: '', confirm: '' },
validate: {
confirm: (value, values) =>
value === values.password ? null : 'The passwords do not match'
}
})
type useForm = <Values, Transformed = Values>(
options: UseFormOptions<Values, Transformed>
) => {
values: Values
errors: Record<string, string>
submitting: boolean
getInputProps: (
path: string,
options?: { type?: 'input' | 'checkbox' }
) => InputProps
onSubmit: (
handleValues: (values: Transformed, event?: React.FormEvent) => unknown,
handleErrors?: (errors: Record<string, string>, values: Values) => void
) => (event?: React.FormEvent) => Promise<void>
onReset: (event?: React.FormEvent) => void
reset: () => void
initialize: (values: Values) => void
getValues: () => Values
getTransformedValues: () => Transformed
setInitialValues: (values: Values) => void
resetDirty: (values?: Values) => void
resetTouched: () => void
validate: () => { hasErrors: boolean; errors: Record<string, string> }
validateField: (path: string) => boolean
setFieldValue: (path: string, value: unknown) => void
setValues: (values: Partial<Values>) => void
setErrors: (errors: Record<string, string>) => void
setFieldError: (path: string, message: string) => void
clearErrors: () => void
clearFieldError: (path: string) => void
insertListItem: (path: string, item: unknown, index?: number) => void
removeListItem: (path: string, index: number) => void
reorderListItem: (path: string, indexes: { from: number; to: number }) => void
replaceListItem: (path: string, index: number, item: unknown) => void
isDirty: (path?: string) => boolean
isValid: (path?: string) => boolean
isTouched: (path?: string) => boolean
getTouched: () => Record<string, boolean>
setFieldTouched: (path: string, touched?: boolean) => void
}
| Option | Description | Type | Default |
|---|---|---|---|
| initialValues | values of the form, also the base for reset/isDirty | Values | - |
| validate | rules by path, or a function that returns all errors | Record<string, rule> | (values) => Record<string, string> | - |
| validateInputOnChange | validate every field, or only the listed paths, on change | boolean | string[] | false |
| validateInputOnBlur | validate every field, or only the listed paths, on blur | boolean | string[] | false |
| transformValues | shapes the values onSubmit hands to its handler | (values: Values) => Transformed | - |
| clearInputErrorOnChange | clear the error of a field when it changes | boolean | true |
| onValuesChange | called with the new values after every change | (values: Values) => void | - |
| Type | Returns | Use with |
|---|---|---|
'input' | value, onChange, onBlur (+ error, errorMessage) | Input, Textarea, NumberInput, Select, Combobox, Slider, DatePicker, TagsInput and other fields |
'checkbox' | checked, onChange, onBlur (+ error, errorMessage) | Checkbox, Toggle |
error and errorMessage only come back while the field has an error. Spread them on fields that accept both: Input, Textarea, NumberInput, TagsInput, Select, Checkbox, Radio, Radio.Group, Toggle and Slider. On fields without them, such as SegmentedControl, pass only value and onChange, or the props reach the DOM as unknown attributes. onBlur only fires on fields that have it, such as Input and Textarea, so the other fields count as touched once their value changes.
| Validator | Fails when |
|---|---|
| isNotEmpty(message) | empty string, empty list, false, null or undefined |
| isEmail(message) | the value is not an e-mail |
| matches(regex, message) | the value is not a string that matches the pattern |
| hasLength(length, message) | the length is out of n or { min, max } |
isInRange({ min, max }, message) | the value is not a number inside the range |
| matchesField(path, message) | the value differs from the field at path |
| Name | Description |
|---|---|
<FormProvider form={form}> | shares the form with every component below it |
useFormContext<Values>() | returns the shared form, and throws outside a FormProvider |