Skip to main content
The useField composable creates and manages an individual form field in Vue applications.

Import

import { useField } from '@tanstack/vue-form'

Signature

function useField<
  TParentData,
  TName extends DeepKeys<TParentData>,
  TData extends DeepValue<TParentData, TName>,
  // ... additional type parameters
>(
  opts: UseFieldOptions<TParentData, TName, TData, ...>
): {
  api: FieldApi<TParentData, TName, TData, ...> & VueFieldApi<...>
  state: Readonly<Ref<FieldState<TData>>>
}

Parameters

opts
UseFieldOptions<TParentData, TName, TData>
required
Configuration object for the field.
opts.form
FormApi<TParentData>
required
The parent form API instance.
opts.name
TName
required
The field name as a path string (e.g., ‘user.firstName’ or ‘items[0].name’).
opts.defaultValue
TData
The default value for the field.
opts.validators
FieldValidators<TParentData, TName, TData>
Validation functions for the field.
opts.validators.onChange
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs on every change.
opts.validators.onChangeAsync
FieldAsyncValidateOrFn<TParentData, TName, TData>
Async validator that runs on change.
opts.validators.onBlur
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs when the field loses focus.
opts.validators.onMount
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs when the field is mounted.
opts.asyncDebounceMs
number
Debounce time in milliseconds for async validation. Default is 500ms.
opts.asyncAlways
boolean
If true, async validation runs even if sync validation fails.

Return Value

api
FieldApi<TParentData, TName, TData> & VueFieldApi
The field API instance.
name
TName
The field name.
state
FieldState<TData>
The current field state including value, errors, and metadata.
handleChange
(value: TData) => void
Update the field value.
handleBlur
() => void
Mark the field as touched.
pushValue
(value: TData extends Array<infer U> ? U : never) => void
Add a value to an array field.
removeValue
(index: number) => void
Remove a value from an array field.
Field
FieldComponent
A nested Field component for creating sub-fields.
state
Readonly<Ref<FieldState<TData>>>
A reactive reference to the field state.
state.value
TData
The current field value.
state.meta
FieldMeta
Field metadata.
state.meta.errors
string[]
Current validation errors.
state.meta.isTouched
boolean
Whether the field has been touched.
state.meta.isDirty
boolean
Whether the field value has changed.
state.meta.isValidating
boolean
Whether async validation is in progress.

Usage Example

<script setup lang="ts">
import { useForm } from '@tanstack/vue-form'

interface FormData {
  email: string
}

const form = useForm<FormData>({
  defaultValues: {
    email: '',
  },
  onSubmit: async ({ value }) => {
    console.log('Email:', value.email)
  },
})

const emailField = form.useField({
  name: 'email',
  validators: {
    onChange: ({ value }) => {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
      return !emailRegex.test(value) ? 'Invalid email address' : undefined
    },
  },
})
</script>

<template>
  <div>
    <label :htmlFor="emailField.api.name">Email:</label>
    <input
      :id="emailField.api.name"
      :name="emailField.api.name"
      :value="emailField.api.state.value"
      @input="(e) => emailField.api.handleChange((e.target as HTMLInputElement).value)"
      @blur="emailField.api.handleBlur"
    />
    <div v-if="emailField.state.value.meta.isTouched && emailField.state.value.meta.errors.length">
      <span style="color: red">{{ emailField.state.value.meta.errors[0] }}</span>
    </div>
  </div>
</template>

See Also

Build docs developers (and LLMs) love