Skip to content
On this page

useFormHandler

useFormHandler is our composable to handle forms, it takes one object as optional argument and returns various objects and methods that will allow us to handle our forms.

Props

initialValues:

WARNING

Changing the initialValues will trigger a form reset, this means the formState and the values will return to its initial state.

Values which we use to initialize the form, this is useful when we get an initial value state for the form from an external call.

Example

vue
<template>
  <input v-bind="register('firstName')" /> // Should initially be 'John'
  <input v-bind="register('lastName')" /> // Should initially be 'Doe'
  <pre>{{ values }}</pre>
  // Should show the initialized values
</template>
<script setup lang="ts">
import { useFormHandler } from 'vue-form-handler'

const { register, values } = useFormHandler({
  initialValues: {
    firstName: 'John',
    lastName: 'Doe',
  },
})
</script>

interceptor:

Function that allows us to intercept any value assignment, accept or deny it and perform operations before and after the assignment happens.

Params

The interceptor will be called passing an object as a parameter with the following:

attributetypedescription
namestringName of the field that is about to be set
valueanyValue of the field that is about to be set
clearErrorClearErrorAPI - clearError
clearFieldClearFieldAPI - clearField
formStateFormStateAPI - formState
modifiedValuesModifiedValuesAPI - modifiedValues
resetFieldResetFieldAPI - resetField
resetFormResetFormAPI - resetForm
setErrorSetErrorAPI - setError
setValueSetValueAPI - setValue
triggerValidationTriggerValidationAPI - triggerValidation
valuesRecord<string,any>API - values

INFO

As you can see, the interceptor is provided with everything the handler does provide but in a separate context.

Expected return

The interceptor expects a type of boolean or a Promise<boolean>, return true to proceed setting the value and false if the value should not be set.

Example

vue
<template>
  <select v-bind="register('continent')" placeholder="Choose your country">
    <option disabled value="null">Choose your continent</option>
    <option value="AM">America</option>
    <option value="AS">Asia</option>
    <option value="EU">Europe</option>
  </select>
  <select v-bind="register('country')" placeholder="Choose your country">
    <option disabled value="null">Choose your country</option>
    <option value="CAN">Canada</option>
    <option value="USA">United States</option>
    <option value="JAP">Japan</option>
    <option value="CHN">China</option>
    <option value="ESP">Spain</option>
    <option value="DEU">Germany</option>
  </select>
</template>
<script setup lang="ts">
import { useFormHandler } from 'vue-form-handler'

const interceptor = ({ name, clearField }) => {
  if (name === 'continent') {
    clearField('country')
  }
  return true
}

const { register } = useFormHandler({
  interceptor,
})
</script>

validate:

Use this function in the case you'd rather perform a custom/different validation when submitting your form

Example

vue
<template @submit.prevent="handleSubmit(successFn)">
  <form>
    <input v-bind="register('firstName')" />
    <input v-bind="register('lastName')" />
    <input type="number" v-bind="register('age')" />
    <input type="submit" />
  </form>
</template>
<script setup lang="ts">
import { useFormHandler } from 'vue-form-handler'

const validation = (values) => values.age && Number(values.age) >= 18
const successFn = (form: Record<string, any>) => {
  console.log({ form })
}

const { register, handleSubmit } = useFormHandler({
  validation,
})
</script>

validationMode:

This option allows you to configure the validation mode or strategy the handler will follow.

nametypedescription
onChangestringValidation will trigger on the change event with each input, and lead to multiple re-renders.
onBlurstringValidation will trigger on the blur event.
onSubmitstringValidation will trigger on the submit event.
alwaysstringValidation will trigger on change and blur events.

WARNING

Using the always validationMode will have a more significant impact on performance.

Return

Type Declarations

ts
export declare const useFormHandler: <
  T extends Record<string, any> = Record<string, any>,
  R extends T = T,
>({
  initialValues,
  interceptor,
  validate,
  validationMode,
  injectionKey,
}?: FormHandlerParams<T, R>) => {
  build: Build<T>
  clearError: (name?: keyof T | undefined) => void
  clearField: (name: keyof T) => Promise<void>
  formState: {
    readonly isDirty: boolean
    readonly isTouched: boolean
    readonly isValid: boolean
    readonly isValidating: boolean
    readonly dirty: import('@vue/reactivity').DeepReadonly<
      import('@vue/reactivity').UnwrapRef<Record<keyof T, boolean>>
    >
    readonly touched: import('@vue/reactivity').DeepReadonly<
      import('@vue/reactivity').UnwrapRef<Record<keyof T, boolean>>
    >
    readonly errors: import('@vue/reactivity').DeepReadonly<
      import('@vue/reactivity').UnwrapRef<Record<keyof T, string | undefined>>
    >
    readonly validating: import('@vue/reactivity').DeepReadonly<
      import('@vue/reactivity').UnwrapRef<Record<keyof T, boolean>>
    >
  }
  handleSubmit: (
    successFn: HandleSubmitSuccessFn,
    errorFn?: HandleSubmitErrorFn
  ) => Promise<void>
  modifiedValues: <TModified extends T>() => TModified
  register: (name: keyof T, options?: RegisterOptions) => RegisterReturn
  resetField: (name: keyof T) => void
  resetForm: () => void
  setError: (name: keyof T, error: string) => void
  setValue: (name: keyof T, value?: any) => Promise<void>
  triggerValidation: (name?: keyof T | undefined) => Promise<void>
  unregister: (name: keyof T) => void
  values: import('@vue/reactivity').DeepReadonly<
    import('@vue/reactivity').UnwrapNestedRefs<T>
  >
}

Released under the MIT License.