useForm — Formularios
useForm proporciona gestión de estado de formularios con validación, detección de errores visual y auto-sync de campos relacionados.
Uso básico
Section titled “Uso básico”const { formData, // shallowReactive con los valores actuales invalidFields, // computed: true si hay al menos un campo inválido markFieldAsTouched, // marca campo como "tocado" para mostrar errores fillFormData, // rellena programáticamente (suprime watchers) getFieldValidation // retorna { valid, showError } por campo} = useForm({ name: '', email: '', phone: '', country: '', code: ''})formData
Section titled “formData”Objeto shallowReactive con los valores. Se usa directamente con v-model:
<input v-model="formData.name" @blur="markFieldAsTouched('name')" /><span v-if="getFieldValidation('name').showError">Campo requerido</span>Validación y campos tocados
Section titled “Validación y campos tocados”Los errores solo se muestran después de que el usuario interactúe con el campo:
markFieldAsTouched('email')// Ahora getFieldValidation('email').showError puede ser true
const { valid, showError } = getFieldValidation('email')// valid: si el campo pasa validación// showError: solo true si es inválido Y fue tocadoinvalidFields
Section titled “invalidFields”// Deshabilitar botón de submit si hay errores<button :disabled="invalidFields">Enviar</button>Es true si cualquier campo del formulario no pasa validación.
fillFormData
Section titled “fillFormData”Para rellenar el formulario programáticamente (ej: datos del usuario logueado):
fillFormData({ name: user.name, email: user.email, country: user.country})Importante: Suprime watchers durante el llenado para evitar side-effects no deseados.
Auto-sync country → code
Section titled “Auto-sync country → code”Si el formulario tiene campos country y code, cambiar el país auto-actualiza el código telefónico:
// Usuario selecciona "México"formData.country = 'MX'// Automáticamente: formData.code = '+52'Usa internamente la constante countriesPhone.ts para el mapeo.
Ejemplo completo
Section titled “Ejemplo completo”<template> <form @submit.prevent="handleSubmit"> <input v-model="formData.name" @blur="markFieldAsTouched('name')" :class="{ 'border-red-500': getFieldValidation('name').showError }" /> <input v-model="formData.email" type="email" @blur="markFieldAsTouched('email')" /> <button :disabled="invalidFields">Enviar</button> </form></template>
<script setup lang="ts">const { formData, invalidFields, markFieldAsTouched, getFieldValidation } = useForm({ name: '', email: ''})
function handleSubmit() { // formData ya tiene los valores tipados}</script>