skills/harlan-zw/vue-ecosystem-skills/tanstack-vue-form-skilld

tanstack-vue-form-skilld

SKILL.md

TanStack/form @tanstack/vue-form

Powerful, type-safe forms for Vue.

Version: 1.28.5 (Mar 2026) Deps: @tanstack/vue-store@^0.9.1, @tanstack/form-core@1.28.5 Tags: latest: 1.28.5 (Mar 2026)

References: Docs — API reference, guides

API Changes

This section documents version-specific API changes for @tanstack/vue-form.

  • BREAKING: field.errors — v1.28.0 flattens errors by default ([error] not [[error]]), use disableErrorFlat: true to restore old nested behavior source

  • DEPRECATED: field.getValue() — use field.state.value instead as direct accessor methods on FieldApi are deprecated in favor of state access source

  • NEW: field.parseValueWithSchema() — validates field value against Standard Schema V1 without affecting internal field error state source

  • NEW: form.parseValuesWithSchema() — form-level Standard Schema V1 validation helper for third-party schemas like Zod or Valibot source

  • NEW: formOptions() — helper to define reusable, type-safe form options with inference outside of the useForm hook source

  • NEW: Field component — declarative Vue component alternative to useField for defining form fields directly in templates source

  • NEW: Subscribe component — Vue component for fine-grained subscriptions to form or field state changes to optimize re-renders source

  • NEW: useStore() — Vue hook providing direct, reactive access to the underlying TanStack Store state for the form or field source

  • NEW: resetField()FormApi method to reset a specific field's value and metadata back to its default state source

  • NEW: clearFieldValues()FormApi utility to efficiently remove all items from an array field's data source

  • NEW: setErrorMap() — allows manual overriding of the internal validation error map for custom validation logic source

  • NEW: StandardSchemaV1 — native support for the Standard Schema validation protocol across all validator fields source

  • NEW: mode option — UseFieldOptions now supports explicit 'value' or 'array' modes for better type safety in complex forms

  • NEW: disableErrorFlat — new option in FieldApiOptions to opt-out of automatic error flattening introduced in v1.28.0 source

Also changed: resetFieldMeta() new helper · insertFieldValue() array utility · moveFieldValues() array utility · swapFieldValues() array utility · FieldApi.getInfo() metadata helper · VueFieldApi interface stabilization · VueFormApi interface stabilization

Best Practices

  • Use formOptions() to define type-safe, reusable form configurations that can be shared across components or used for better type inference source
const options = formOptions({
  defaultValues: { email: '' },
  validators: {
    onChange: z.object({ email: z.string().email() })
  }
})

const form = useForm(options)
  • Link field validations with onChangeListenTo to trigger re-validation when dependent field values change, such as password confirmations source
<form.Field
  name="confirm_password"
  :validators="{
    onChangeListenTo: ['password'],
    onChange: ({ value, fieldApi }) =>
      value !== fieldApi.form.getFieldValue('password') ? 'Passwords do not match' : undefined
  }"
>
  • Implement async-debounce-ms at the field or validator level to throttle expensive asynchronous validation calls like API checks source
<form.Field
  name="username"
  :async-debounce-ms="500"
  :validators="{
    onChangeAsync: async ({ value }) => checkUsername(value)
  }"
>
  • Parse Standard Schemas manually within onSubmit to retrieve transformed values, as the form state preserves the raw input data source
const form = useForm({
  onSubmit: ({ value }) => {
    // schema.parse converts string to number if transform is defined
    const validatedData = loginSchema.parse(value)
    api.submit(validatedData)
  }
})
  • Pass custom metadata via onSubmitMeta to differentiate between multiple submission actions within a single onSubmit handler source
<button @click="form.handleSubmit({ action: 'save_draft' })">Save Draft</button>
<button @click="form.handleSubmit({ action: 'publish' })">Publish</button>
  • Combine canSubmit with isPristine to ensure the submit button remains disabled until the user has actually interacted with the form source
<template v-slot="{ canSubmit, isPristine }">
  <button :disabled="!canSubmit || isPristine">Submit</button>
</template>
  • Use form.useStore with a selector in <script setup> for granular, reactive access to form state without re-rendering on unrelated changes source
const canSubmit = form.useStore((state) => state.canSubmit)
  • Enable asyncAlways: true when you need asynchronous validators to execute regardless of whether synchronous validation has already failed source
// Runs async validation even if local regex check fails
const validators = {
  onChange: ({ value }) => !value.includes('@') ? 'Invalid' : undefined,
  onChangeAsync: async ({ value }) => api.check(value),
  asyncAlways: true
}
  • Return a fields mapping from form-level validators to update errors across multiple fields simultaneously from a single validation logic source
validators: {
  onChange: ({ value }) => ({
    fields: {
      startDate: value.startDate > value.endDate ? 'Must be before end' : undefined,
      endDate: value.startDate > value.endDate ? 'Must be after start' : undefined
    }
  })
}
  • Use reactive objects for defaultValues when binding the form to dynamic or asynchronous data sources like TanStack Query source
const { data } = useQuery(...)
const defaultValues = reactive({
  name: computed(() => data.value?.name ?? '')
})
const form = useForm({ defaultValues })
Weekly Installs
31
GitHub Stars
141
First Seen
Feb 19, 2026
Installed on
github-copilot28
opencode27
codex27
kimi-cli27
gemini-cli27
amp27