useForm

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.

General

Errors show on submit and clear as the user fixes each field.

Nested fields and lists

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)

When to validate

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.

Custom validation

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'
  }
})

APIs

useForm

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
}

UseFormOptions

OptionDescriptionTypeDefault
initialValuesvalues of the form, also the base for reset/isDirtyValues-
validaterules by path, or a function that returns all errorsRecord<string, rule> | (values) => Record<string, string>-
validateInputOnChangevalidate every field, or only the listed paths, on changeboolean | string[]false
validateInputOnBlurvalidate every field, or only the listed paths, on blurboolean | string[]false
transformValuesshapes the values onSubmit hands to its handler(values: Values) => Transformed-
clearInputErrorOnChangeclear the error of a field when it changesbooleantrue
onValuesChangecalled with the new values after every change(values: Values) => void-

getInputProps

TypeReturnsUse 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.

Validators

ValidatorFails 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

FormProvider

NameDescription
<FormProvider form={form}>shares the form with every component below it
useFormContext<Values>()returns the shared form, and throws outside a FormProvider
Edit this page on GitHub