vue-form-use
v0.6.3
Published
Performant, flexible and extensible forms with easy-to-use validation for Vue 3
Readme
vue-form-use
Performant, flexible and extensible forms with easy-to-use validation for Vue 3.
Features
- 🚀 Performant - Minimal re-renders and optimized form state management
- 📦 Lightweight - Small bundle size with zero dependencies (except Vue)
- 🔒 Type-safe - Full TypeScript support with excellent type inference
- 🎯 Flexible - Works with any form library and custom components
- 🔧 Extensible - Easy to integrate with validation libraries
- 🎨 Composable - Built with Vue 3 Composition API
Installation
npm i vue-form-use
# or
pnpm add vue-form-use
# or
yarn add vue-form-useUsage
Basic Example
<script setup lang="ts">
import { useForm } from 'pkg-placeholder'
const form = useForm({
defaultValues: {
username: '',
},
})
const onSubmit = form.handleSubmit((data) => {
console.log('🚀 Submit Data: ', data)
})
</script>
<template>
<form @submit.prevent="onSubmit">
<input :="form.register('username', { required: 'username field cannot be empty!' })">
<span v-if="form.errors.username">errors: {{ form.errors.username?.message }}</span>
<button type="submit">
submit
</button>
</form>
</template>Using Resolver Options
We also support schema-based form validation with Yup, Zod , Superstruct & Joi, where you can pass your schema to useForm as an optional config. It will validate your input data against the schema and return with either errors or a valid result.
<script setup lang="ts">
import { FieldError, useForm } from 'vue-form-use'
import { yupResolver } from 'vue-form-use/resolver/yup'
import * as yup from 'yup'
const schema = yup.object({
name: yup.string().required('Name is required'),
email: yup.string().email('Invalid email').required('Email is required'),
})
const form = useForm({
defaultValues: { name: '' },
resolver: yupResolver(schema),
})
const onSubmit = form.handleSubmit((data) => {
console.log(data)
})
</script>
<template>
<form @submit="onSubmit">
<input :="form.register('name')" placeholder="Name">
{{ form.errors.name?.message }}
<input :="form.register('email')" placeholder="Email">
{{ form.errors.email?.message }}
<button type="submit">
Submit
</button>
</form>
</template>Using Controller Component
For more complex scenarios or when you need fine-grained control, you can use the Controller component:
<script setup lang="ts">
import { Controller, useForm } from 'vue-form-use'
const form = useForm({
defaultValues: {
name: '',
email: '',
},
})
const onSubmit = form.handleSubmit((data) => {
console.log(data)
})
</script>
<template>
<form @submit="onSubmit">
<Controller v-slots="{ field }" :control="form.control" name="name">
<input v-model="field.value" placeholder="Name">
</Controller>
<Controller v-slots="{ field }" :control="form.control" name="email">
<input v-model="field.value" placeholder="Email">
</Controller>
<button type="submit">
Submit
</button>
</form>
</template>Form State
Access form state including errors, validation status, and more:
<script setup lang="ts">
import { useForm } from 'vue-form-use'
const form = useForm({
defaultValues: {
email: '',
},
})
// Access form values (reactive)
const emailValue = computed(() => form.values.email)
// Access form state
const isDirty = computed(() => form.status.isDirty)
const isValid = computed(() => form.status.isValid)
const isSubmitting = computed(() => form.status.isSubmitting)
</script>
<template>
<form>
<input :="form.register('email')">
<p v-if="form.errors.email">
{{ form.errors.email.message }}
</p>
<!-- directly using field values, it has responsiveness -->
{{ form.values.email }}
<!-- or use a computed property -->
{{ emailValue }}
<!-- access form status -->
<p>Is Dirty: {{ isDirty }}</p>
<p>Is Valid: {{ isValid }}</p>
</form>
</template>Reset Form
Reset the form to its default values:
<script setup lang="ts">
import { useForm } from 'vue-form-use'
const form = useForm({
defaultValues: {
name: '',
email: '',
},
})
</script>
<template>
<form>
<input :="form.register('name')">
<input :="form.register('email')">
<button type="button" @click="form.reset()">
Reset
</button>
</form>
</template>API
useForm
The main composable for managing form state.
Parameters
function useForm(props: UseFormProps): UseFormReturndefaultValues- Default values for the form (can be async function)values- Controlled form valuesmode- Validation mode:'onSubmit'|'onBlur'|'onChange'|'onTouched'|'all'(default:'onSubmit')reValidateMode- Re-validation mode:'onChange'|'onBlur'|'onSubmit'(default:'onChange')disabled- Disable the entire formerrors- External controlled errorsresetOptions- Options for reset behavior (keepDirtyValues, keepErrors, etc.)resolver- Validation resolver functioncontext- Custom context object passed to resolvershouldFocusError- Focus the first error field on submit (default:true)shouldUnregister- Unregister fields on unmount (default:false)shouldUseNativeValidation- Use native HTML5 validationcriteriaMode- Error criteria mode:'firstError'|'all'
Returns
values- Reactive form values (the actual form data)state- Form state object containing:isDirty,isValid,isSubmitting, etc.fields- Field-level state for each field (invalid, isDirty, isTouched, etc.)
control- Form control instanceerrors- Field errors objectregister- Register a fieldunregister- Unregister a fieldhandleSubmit- Handle form submissionreset- Reset the formresetField- Reset a specific fieldupdate- Update form valuestrigger- Trigger validationsetError- Set field error manuallyclearError- Clear field errorfocus- Focus a field
Controller
A component for managing individual form fields with scoped slots.
Props
name- Field name (typed)control- Form control instance fromuseForm
Slots
default- Receives{ field, state }where:field- Field props (value, onChange, onBlur, etc.)state- Form state
useController
A composable alternative to the Controller component.
const controller = useController({
control: form.control,
name: 'fieldName',
})TypeScript
Full TypeScript support with excellent type inference:
interface FormValues {
name: string
email: string
age: number
}
const form = useForm<FormValues>({
defaultValues: {
name: '',
email: '',
age: 0,
},
})
// Type-safe field access
form.values.name // string
form.values.email // string
form.values.age // number
// Access form status
form.status.isDirty // boolean
form.status.isValid // boolean
form.status.fields.name.isDirty // boolean
form.status.fields.name.error // FieldError | undefinedLicense
MIT License © 2024-PRESENT Hairyf
