vue-formik

Form management library for Vue.js inspired by Formik - Simple, flexible, and performant form validation and state management
35,965 9
Install
npm install vue-formik
Latest Version:0.3.0
Vue:3
License:LGPL-3.0-or-later
Last Updated:Jun 24, 2026
Links: GitHub  ·  npm
Maintainer: kiran589

🌟Vue-Formik

example workflow GitHub stars LGPLv3 License Npm package version Npm package yearly downloads PRs Welcome Issues

Vue-Formik is a form management library for Vue.js.

Inspired by the powerful Formik library in React, Vue-Formik brings a simple and flexible way to handle form validation and form state management to Vue.js. 🚀

🔥 Key Features

  • 🎯 End-to-end type safety: setFieldValue/getFieldValue infer typed paths (incl. tags[0], address.city) and the value type at that path — autocomplete and compile-time checks for free
  • ✅ Validate with anything: Yup, Zod, Joi, Superstruct, custom rules — or any Standard Schema (Zod, Valibot, ArkType…) via a single adapter
  • 🧩 Familiar Formik API: values / errors / touched / handleSubmit / field arrays — the mental model React developers already know, native to Vue 3
  • 🪝 Headless useField: bind any input (your own or a UI library's) to form state without the bundled components
  • 🔁 Full field-array ops: push, pop, insert, remove, move, swap, replace
  • 🦾 Accessible by default: ARIA wiring, error live-regions, and focus-to-first-error on submit
  • ⚡ Performance Optimized: Debounced validation and efficient dirty checking
  • 🔄 Flexible Configuration: Control validation timing with validateOnChange, validateOnBlur, validateOnMount
  • 🎨 Component Library: Pre-built form components (FormInput, FormTextArea, FormSelectField, FormContentEditable, FormikForm)

💡 Quick Start

npm install vue-formik
# or
pnpm add vue-formik
# or
yarn add vue-formik

Basic Example

<script setup lang="ts">
import { useFormik } from 'vue-formik'

const form = useFormik({
  initialValues: {
    email: '',
    password: ''
  },
  validationSchema: {
    email: (value: string) => {
      if (!value) return 'Email is required'
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return 'Invalid email'
    },
    password: (value: string) => {
      if (!value) return 'Password is required'
      if (value.length < 8) return 'Password must be at least 8 characters'
    }
  },
  onSubmit: async (values) => {
    console.log('Form submitted:', values)
  }
})
</script>

<template>
  <form @submit.prevent="form.handleSubmit">
    <input
      v-model="form.values.email"
      @blur="form.handleFieldBlur"
      @change="form.handleFieldChange"
      type="email"
      name="email"
    />
    <span v-if="form.hasFieldError('email')">
      {{ form.getFieldError('email') }}
    </span>

    <input
      v-model="form.values.password"
      @blur="form.handleFieldBlur"
      @change="form.handleFieldChange"
      type="password"
      name="password"
    />
    <span v-if="form.hasFieldError('password')">
      {{ form.getFieldError('password') }}
    </span>

    <button type="submit" :disabled="form.isSubmitting.value">
      Submit
    </button>
  </form>
</template>

Advanced Configuration

<script setup lang="ts">
import { useFormik } from 'vue-formik'
import * as Yup from 'yup'

const form = useFormik({
  initialValues: {
    name: '',
    email: ''
  },
  yupSchema: Yup.object({
    name: Yup.string().required('Name is required'),
    email: Yup.string().email('Invalid email').required('Email is required')
  }),
  validateOnChange: true,
  validateOnBlur: true,
  validateOnMount: false,
  validationDebounce: 300, // Debounce validation by 300ms
  onSubmit: async (values) => {
    console.log('Submitted:', values)
  }
})
</script>

Type-safe field access

When you type your form (or let it be inferred from initialValues), field paths and values are fully typed — including nested objects and array indices:

import { useFormik } from 'vue-formik'

const form = useFormik({
  initialValues: {
    name: '',
    address: { city: '' },
    tags: [] as string[],
  },
})

form.setFieldValue('address.city', 'Kathmandu') // ✅ ok
form.setFieldValue('tags[0]', 'vue')            // ✅ ok
form.setFieldValue('name', 123)                 // ❌ type error: expected string
form.setFieldValue('nope', 'x')                 // ❌ type error: not a valid path

const city = form.getFieldValue('address.city') // string | undefined

Validate with any Standard Schema

Standard Schema is a shared interface implemented by Zod, Valibot, ArkType and others. Pass any of them via the single standardSchema option:

import { useFormik } from 'vue-formik'
import * as v from 'valibot' // or zod, arktype, …

const form = useFormik({
  initialValues: { email: '' },
  standardSchema: v.object({ email: v.pipe(v.string(), v.email('Invalid email')) }),
})

Headless useField

Bind any input — including third-party UI components — without the bundled components:

import { useField } from 'vue-formik'

const { value, error, hasError, onInput, onBlur, attrs } = useField('email')

Dynamic lists with useFieldArray

import { useFieldArray } from 'vue-formik'

const fa = useFieldArray(form)
fa.push('tags', 'new')
fa.insert('tags', 0, 'first')
fa.move('tags', 0, 2)
fa.swap('tags', 1, 3)
fa.remove('tags', 2)
fa.replace('tags', 0, 'updated')

📚 Documentation

See the full documentation for more information.

v0.3.0 note: setFieldValue / setFieldTouched / getFieldValue are now strictly typed via NestedPaths/NestedValue. If you were passing dynamically-built field-name strings, cast them (name as NestedPaths<typeof values>) or type the form explicitly.

🤝 Contributing

Want to help shape Vue-Formik? Contributions are welcome! Check out our CONTRIBUTING.md (link coming soon) for more details.

📢 Stay Updated

Follow the project for updates, ✨ new features, bug fixes, and a roadmap for the future!

👨‍💻 Happy Coding! ❤️

Related Packages

@xuanmo/v-form

* 目前已经集成的组件(Address/Checkbox/DatePicker/Input/Radio/Select/Text/Switch...

8,127 86
@ezijing/vue-form

基于Vue Element-UI的表单

3,486
@vigilio/vue-form

Now you can use this vue form library

1,009 2
jenesius-vue-form

Heavy form system for Vue.js

4,940 45

Version History

Version Released License
0.3.0 LGPL-3.0-or-later
0.2.4 LGPL-3.0-or-later
0.2.3 LGPL-3.0-or-later
0.2.2 LGPL-3.0-or-later
0.2.1 LGPL-3.0-or-later