Skip to content
On this page

useForm

useForm() is a custom Vue composition api that makes you to easily manage form values and state.

Usage

The following code excerpt demonstrates a basic usage example:

vue
<script setup lang="ts">
import { useForm } from '@vorms/core'

const { errors, dirty, register, handleSubmit, handleReset } = useForm({
  initialValues: {
    drink: '',
    sugar: 30,
  },
  validate (values) {
    const errors: Record<string, any> = {}

    if (!values.drink) {
      errors.drink = 'This is required!!'
    }

    return errors
  },

  onSubmit(data, { setSubmitting }) {
    // If `onSubmit()` function is synchronous, you need to call 
    // `setSubmitting(false)` yourself.
    setSubmitting(false)
  }
})

// Basic usage
// The `attrs` need to be bind on <input> to support `validateMode`
// and `reValidateMode`.
const { value: drink, attrs: drinkFieldAttrs } = register('drink')

// Add field level validation.
const { value: sugar, attrs: sugarFieldAttrs } = register('sugar', {
  validate(value) {
    return value > 100 ? 'This max number is 100' : undefined
  }
})
</script>

<template>
  <form @submit="handleSubmit" @reset="handleReset">
    <div>
      <input v-model="drink" type="text" v-bind="drinkFieldAttrs">
      <div>{{ errors.drink }}</div>
    </div>
    
    <div>
      <input v-model.number="sugar" type="number" v-bind="sugarFieldAttrs">
      <div>{{ errors.sugar }}</div>
    </div>

    <button type="reset">Reset</button>
    <button type="submit">Submit</button>
  </form>
</template>
<script setup lang="ts">
import { useForm } from '@vorms/core'

const { errors, dirty, register, handleSubmit, handleReset } = useForm({
  initialValues: {
    drink: '',
    sugar: 30,
  },
  validate (values) {
    const errors: Record<string, any> = {}

    if (!values.drink) {
      errors.drink = 'This is required!!'
    }

    return errors
  },

  onSubmit(data, { setSubmitting }) {
    // If `onSubmit()` function is synchronous, you need to call 
    // `setSubmitting(false)` yourself.
    setSubmitting(false)
  }
})

// Basic usage
// The `attrs` need to be bind on <input> to support `validateMode`
// and `reValidateMode`.
const { value: drink, attrs: drinkFieldAttrs } = register('drink')

// Add field level validation.
const { value: sugar, attrs: sugarFieldAttrs } = register('sugar', {
  validate(value) {
    return value > 100 ? 'This max number is 100' : undefined
  }
})
</script>

<template>
  <form @submit="handleSubmit" @reset="handleReset">
    <div>
      <input v-model="drink" type="text" v-bind="drinkFieldAttrs">
      <div>{{ errors.drink }}</div>
    </div>
    
    <div>
      <input v-model.number="sugar" type="number" v-bind="sugarFieldAttrs">
      <div>{{ errors.sugar }}</div>
    </div>

    <button type="reset">Reset</button>
    <button type="submit">Submit</button>
  </form>
</template>

Params

initialValues (Required)

This is initial values of the form and will be used as the basis for the dirty comparison.

  • Type

    ts
    type Values = Record<string, any>
    type Values = Record<string, any>

initialErrors

This is initial errors of the form.

  • Type FormErrors<Values>
  • Default: undefined

initialTouched

This is initial touched status of the form.

  • Type FormTouched<Values>
  • Default: undefined

validateMode

This option allows you to configure the validation strategy before first submit.

  • Type 'blur' | 'input' | 'change' | 'submit'
  • Default 'submit'

reValidateMode

This option allows you to configure the validation strategy after first submit. By default, validation is triggered during the input change event.

INFO

Even if your reValidationMode is not set to submit, Vorms will revalidate before submitting.

  • Type 'blur' | 'input' | 'change' | 'submit'
  • Default 'change'

validateOnMounted

This option allows you to configure that whether the validation should run or not when component is mounted.

  • Type boolean
  • Default false

validate

The validate is a form level validation. This property accepts the form's values as the argument. You could return the errors object or undefined to determine whether those values are valid or not.

  • Type

    ts
    function validate(values: Values): void | object | Promise<FormErrors<Values>>
    function validate(values: Values): void | object | Promise<FormErrors<Values>>

This validate value could either be:

  1. Synchronous function and return the errors object.

    ts
    import { useForm } from '@vorms/core'
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate(values) {
        const errors = {}
    
        if(!values.name) {
          errors.name = 'name is required.'
        }
    
        if(typeof values.age !== 'number') {
          errors.age = 'age should be a number.'
        }
    
        return errors
      },
      onSubmit(values) {
        console.log(values)
      }
    })
    import { useForm } from '@vorms/core'
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate(values) {
        const errors = {}
    
        if(!values.name) {
          errors.name = 'name is required.'
        }
    
        if(typeof values.age !== 'number') {
          errors.age = 'age should be a number.'
        }
    
        return errors
      },
      onSubmit(values) {
        console.log(values)
      }
    })
  2. Asynchronous function and return a Promise that is resolve an object containing errors.

    ts
    import { useForm } from '@vorms/core'
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate() {
        return new Promise((resolve) => {
          setTimeout(() => {
            const errors = {}
    
            if(!values.name) {
              errors.name = 'name is required.'
            }
    
            if(typeof values.age !== 'number') {
              errors.age = 'age should be a number.'
            }
    
            resolve(errors)
          }, 300)
        })
      },
      onSubmit(values) {
        console.log(values)
      }
    })
    import { useForm } from '@vorms/core'
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate() {
        return new Promise((resolve) => {
          setTimeout(() => {
            const errors = {}
    
            if(!values.name) {
              errors.name = 'name is required.'
            }
    
            if(typeof values.age !== 'number') {
              errors.age = 'age should be a number.'
            }
    
            resolve(errors)
          }, 300)
        })
      },
      onSubmit(values) {
        console.log(values)
      }
    })
  3. Use @vorms/resolvers to integrate external validation libraries such as Yup or Zod.

    bash
    npm install @vorms/resolvers
    npm install @vorms/resolvers
    ts
    import { useForm } from '@vorms/core'
    import { yupResolver } from '@vorms/resolvers/yup';
    import * as yup from 'yup';
    
    const schema = yup.object().shape({
      name: yup.string().required('Name is required!!'),
      age: yup.number().required('Age is required!!')
    })
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate: yupResolver(schema),
      onSubmit(values) {
        console.log(values)
      }
    })
    import { useForm } from '@vorms/core'
    import { yupResolver } from '@vorms/resolvers/yup';
    import * as yup from 'yup';
    
    const schema = yup.object().shape({
      name: yup.string().required('Name is required!!'),
      age: yup.number().required('Age is required!!')
    })
    
    const { values } = useForm({
      initialValues: {
        name: '',
        age: 10
      },
      validate: yupResolver(schema),
      onSubmit(values) {
        console.log(values)
      }
    })

onSubmit (Required)

This is your form submission handler, witch will pass your form's values. But this will not be called if the validation failed.

  • Type

    ts
    function onSubmit (values: Values, helper: FormSubmitHelper): void | Promise<any>
    function onSubmit (values: Values, helper: FormSubmitHelper): void | Promise<any>
    ts
    interface FormSubmitHelper {
      setSubmitting: (isSubmitting: boolean) => void;
      initialValues: Values;
    }
    interface FormSubmitHelper {
      setSubmitting: (isSubmitting: boolean) => void;
      initialValues: Values;
    }

Parameters

  • values: the validated values.

  • helper: some states or methods that can be helpful when submitting the form.

    NameDescription
    setSubmittingSet isSubmitting imperatively.
    initialValuesForm initial values.

Important

When the onSubmit() function is asynchronous, the isSubmitting variable is automatically reset to false upon completion. Conversely, if onSubmit() is synchronous, you must manually call setSubmitting(false) to reset isSubmitting.

onInvalid

This is your invalid handler, called when the form is submitted with invalid values.

Returns

values

Current form values.

  • Type Values

Note

If you use values with v-model directly, validation will only be called before submit.

errors

An object containing all the current validation errors. The shape will match the shape of the form's values.

  • Type ComputedRef<FormErrors<Values>>

touched

An object containing all fields that have ever been touched. The shape will match the shape of the form's values.

  • Type ComputedRef<FormTouched<Values>>

dirty

Return true if current values are not deeply equal to initialValues.

  • Type ComputedRef<boolean>

setValues

This function allows you to manually update form values.

  • Type (values: Values, shouldValidate?: boolean)

setFieldValue

This function allows you to manually set the specific value of field.

  • Type (name: string, value: unknown, shouldValidate?: boolean)

setErrors

This function allows you to manually set form errors.

  • Type (errors: FormErrors<Values>)

setFieldError

This function allows you to manually set the specific error of field.

  • Type (name: string, error: string | string[] | Record<string, any> | undefined)

submitCount

The number of times user attempted to submit.

  • Type ComputedRef<number>

isSubmitting

Return true when form is submitting, If onSubmit() is a synchronous function, then you need to call setSubmitting(false) yourself.

  • Type Ref<boolean>

isValidating

Return true when running validation.

  • Type ComputedRef<boolean>

resetForm

Reset the entire form state. There are optional arguments that allow you to set the state to what you want.

  • Type

    ts
    function resetForm(nextState?: Partial<FormResetState<Values>>): void
    
    interface FormResetState<Values> {
      //Form values.
      values: Values;
      // An object containing the name of the field that has been touched.
      touched: FormTouched<Values>;
      // An object containing the name of the field that has error.
      errors: FormErrors<Values>;
      // The number of times user attempted to submit.
      submitCount: number;
    }
    function resetForm(nextState?: Partial<FormResetState<Values>>): void
    
    interface FormResetState<Values> {
      //Form values.
      values: Values;
      // An object containing the name of the field that has been touched.
      touched: FormTouched<Values>;
      // An object containing the name of the field that has error.
      errors: FormErrors<Values>;
      // The number of times user attempted to submit.
      submitCount: number;
    }

register

This method allows you to get the specific field value, meta (state) and attribute, you can also add validation for that field.

  • Type

    ts
    function register<Value>(name: MaybeRefOrGetter<string>,  options?: FieldRegisterOptions<Value>): UseFormRegisterReturn<Value>
    function register<Value>(name: MaybeRefOrGetter<string>,  options?: FieldRegisterOptions<Value>): UseFormRegisterReturn<Value>
    Show Type Detail
    ts
    interface FieldRegisterOptions<Value> {
      validate?: FieldValidator<Value>;
    }
    
    type FieldValidator<Value> = (value: Value) => string | void | Promise<string | void>
    
    type UseFormRegisterReturn<Value> =  {
      value: WritableComputedRef<Value>;
      dirty: ComputedRef<boolean>;
      error: ComputedRef<string | undefined>;
      touched: ComputedRef<boolean | undefined>;
      attrs: ComputedRef<FieldAttrs>;
    }
    
    interface FieldAttrs {
      name: string;
      onBlur(event: Event): void;
      onChange(): void;
      onInput(): void
    }
    interface FieldRegisterOptions<Value> {
      validate?: FieldValidator<Value>;
    }
    
    type FieldValidator<Value> = (value: Value) => string | void | Promise<string | void>
    
    type UseFormRegisterReturn<Value> =  {
      value: WritableComputedRef<Value>;
      dirty: ComputedRef<boolean>;
      error: ComputedRef<string | undefined>;
      touched: ComputedRef<boolean | undefined>;
      attrs: ComputedRef<FieldAttrs>;
    }
    
    interface FieldAttrs {
      name: string;
      onBlur(event: Event): void;
      onChange(): void;
      onInput(): void
    }
  • Example

    vue
    <script setup lang="ts">
    const { register } = useForm({
      initialValues: {
        drink: 'Bubble Tea'
      }
    })
    
    const { value, attrs } = register('drink', {
      // Field level validation
      validate(value) {
        return !value ? 'What do you want to drink ?' : undefined
      }
    })
    </script>
    
    <template>
      <input v-model="value" type="text" v-bind="attrs" />
    </template>
    <script setup lang="ts">
    const { register } = useForm({
      initialValues: {
        drink: 'Bubble Tea'
      }
    })
    
    const { value, attrs } = register('drink', {
      // Field level validation
      validate(value) {
        return !value ? 'What do you want to drink ?' : undefined
      }
    })
    </script>
    
    <template>
      <input v-model="value" type="text" v-bind="attrs" />
    </template>

handleSubmit

Submission handler. It will call event.preventDefault() internally, If event is passed.

  • Type

    ts
    function handleSubmit(event?: Event): void
    function handleSubmit(event?: Event): void

handleReset

Reset handler. It will call event.preventDefault() internally, If event is passed.

  • Type

    ts
    function handleReset(event?: Event): void
    function handleReset(event?: Event): void

validateForm

Validator of the form. It will run the form level validation.

  • Type

    ts
    function validateForm(values?: Values): Promise<FormErrors<Values>>
    function validateForm(values?: Values): Promise<FormErrors<Values>>

validateField

Validator for specific field, if this field's validation has been registered.

  • Type

    ts
    function validateField(name: string): Promise<void>
    function validateField(name: string): Promise<void>

Released under the MIT License.