Validación de Formularios Reactivos en Vue 3 con VeeValidate y Yup: Guía Completa
Este tutorial te guiará a través de la implementación de validación de formularios reactivos en tus aplicaciones Vue 3 utilizando las poderosas bibliotecas VeeValidate y Yup. Aprenderás a definir esquemas de validación, mostrar mensajes de error y gestionar el estado del formulario de manera eficiente.
La gestión de formularios es una parte esencial de casi cualquier aplicación web. Garantizar que los datos ingresados por el usuario sean válidos es crucial para mantener la integridad de la aplicación y proporcionar una buena experiencia de usuario. En Vue 3, la combinación de VeeValidate y Yup ofrece una solución elegante y robusta para la validación de formularios reactivos.
🚀 ¿Por qué VeeValidate y Yup?
Existen varias formas de validar formularios en Vue.js, desde la validación manual hasta el uso de bibliotecas. VeeValidate se destaca por su enfoque declarativo y su profunda integración con Vue. Permite definir reglas de validación directamente en tu plantilla o mediante esquemas. Cuando se combina con Yup, una biblioteca de validación de esquemas, se obtiene una solución extremadamente potente y flexible.
VeeValidate
VeeValidate es una biblioteca de validación para Vue.js que simplifica el proceso de añadir reglas de validación a tus formularios. Ofrece componentes para campos (Field), formularios (Form) y mensajes de error (ErrorMessage), además de una Composition API que se integra perfectamente con Vue 3.
Yup
Yup es un constructor de esquemas JavaScript para analizar y validar valores. Permite definir la forma, los requisitos y las reglas de validación para objetos JavaScript de forma declarativa. Su integración con VeeValidate a través de toTypedSchema lo convierte en el compañero perfecto para la validación basada en esquemas.
🛠️ Configuración Inicial del Proyecto
Antes de sumergirnos en la validación, necesitamos configurar un proyecto básico de Vue 3 e instalar las dependencias necesarias.
1. Crear un Proyecto Vue 3
Si aún no tienes un proyecto Vue 3, puedes crearlo usando create-vue (la forma recomendada):
npm init vue@latest
# o
yarn create vue@latest
# o
pnpm create vue@latest
Sigue las indicaciones. Para este tutorial, puedes elegir las opciones predeterminadas o no incluir TypeScript y Pinia para simplificar, a menos que ya los uses. Navega a tu directorio de proyecto:
cd my-vue-form-app
2. Instalar VeeValidate y Yup
Ahora, instalaremos las bibliotecas principales. VeeValidate tiene una integración oficial para Yup que usaremos:
npm install vee-validate yup @vee-validate/yup
# o
yarn add vee-validate yup @vee-validate/yup
# o
pnpm add vee-validate yup @vee-validate/yup
Una vez instaladas, estamos listos para empezar a construir nuestro formulario.
📝 Creando un Formulario Básico
Vamos a crear un formulario de registro simple con campos para nombre de usuario, correo electrónico y contraseña. Empezaremos sin validación para luego añadirla progresivamente.
Crea un nuevo componente llamado RegistrationForm.vue dentro de la carpeta src/components.
<template>
<form @submit.prevent="handleSubmit">
<h2>Registro de Usuario</h2>
<div class="form-group">
<label for="username">Nombre de Usuario:</label>
<input type="text" id="username" v-model="formData.username">
</div>
<div class="form-group">
<label for="email">Correo Electrónico:</label>
<input type="email" id="email" v-model="formData.email">
</div>
<div class="form-group">
<label for="password">Contraseña:</label>
<input type="password" id="password" v-model="formData.password">
</div>
<div class="form-group">
<label for="confirmPassword">Confirmar Contraseña:</label>
<input type="password" id="confirmPassword" v-model="formData.confirmPassword">
</div>
<button type="submit">Registrarse</button>
</form>
</template>
<script setup>
import { reactive } from 'vue';
const formData = reactive({
username: '',
email: '',
password: '',
confirmPassword: ''
});
const handleSubmit = () => {
console.log('Formulario enviado:', formData);
alert('Formulario enviado (sin validación): ' + JSON.stringify(formData, null, 2));
// Aquí iría la lógica para enviar el formulario a un API, etc.
};
</script>
<style scoped>
form {
max-width: 500px;
margin: 50px auto;
padding: 30px;
border: 1px solid #e0e0e0;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
background-color: #fff;
}
h2 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #555;
}
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 16px;
box-sizing: border-box;
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus {
border-color: #007bff;
outline: none;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
button {
width: 100%;
padding: 12px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 18px;
font-weight: bold;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0056b3;
}
</style>
Ahora, importa este componente en App.vue para verlo en acción:
<template>
<RegistrationForm />
</template>
<script setup>
import RegistrationForm from './components/RegistrationForm.vue';
</script>
<style>
/* Estilos globales */
body {
font-family: 'Arial', sans-serif;
background-color: #f4f7f6;
margin: 0;
padding: 0;
}
</style>
Verifica que el formulario se renderice correctamente en tu navegador.
✨ Integrando VeeValidate: El Componente Form
VeeValidate proporciona un componente Form que envuelve tu formulario HTML y se encarga de la gestión del estado de validación. Reemplazaremos la etiqueta <form> nativa por <Form>.
1. Actualizar RegistrationForm.vue
Modifica RegistrationForm.vue para usar Form, Field y ErrorMessage.
<template>
<!-- 🎯 Usamos el componente Form de VeeValidate -->
<Form @submit="handleSubmit" :validation-schema="schema">
<h2>Registro de Usuario</h2>
<div class="form-group">
<label for="username">Nombre de Usuario:</label>
<!-- 📖 Usamos el componente Field para cada campo -->
<Field name="username" type="text" id="username" />
<!-- ⚠️ Componente para mostrar errores -->
<ErrorMessage name="username" class="error-message" />
</div>
<div class="form-group">
<label for="email">Correo Electrónico:</label>
<Field name="email" type="email" id="email" />
<ErrorMessage name="email" class="error-message" />
</div>
<div class="form-group">
<label for="password">Contraseña:</label>
<Field name="password" type="password" id="password" />
<ErrorMessage name="password" class="error-message" />
</div>
<div class="form-group">
<label for="confirmPassword">Confirmar Contraseña:</label>
<Field name="confirmPassword" type="password" id="confirmPassword" />
<ErrorMessage name="confirmPassword" class="error-message" />
</div>
<button type="submit">Registrarse</button>
</Form>
</template>
<script setup>
import { Form, Field, ErrorMessage } from 'vee-validate';
import * as yup from 'yup'; // Importamos Yup
import { toTypedSchema } from '@vee-validate/yup'; // Para integrar Yup con VeeValidate
// Definimos el esquema de validación con Yup
const schema = toTypedSchema(
yup.object({
username: yup.string()
.required('El nombre de usuario es obligatorio')
.min(3, 'El nombre de usuario debe tener al menos 3 caracteres')
.max(20, 'El nombre de usuario no puede exceder los 20 caracteres'),
email: yup.string()
.required('El correo electrónico es obligatorio')
.email('Debe ser un correo electrónico válido'),
password: yup.string()
.required('La contraseña es obligatoria')
.min(6, 'La contraseña debe tener al menos 6 caracteres'),
confirmPassword: yup.string()
.required('Confirma tu contraseña')
.oneOf([yup.ref('password')], 'Las contraseñas no coinciden'), // Regla para que coincida con 'password'
})
);
// La función handleSubmit recibe el objeto de valores del formulario si la validación es exitosa
const handleSubmit = (values) => {
console.log('Formulario enviado y validado:', values);
alert('Registro exitoso! \n' + JSON.stringify(values, null, 2));
// Aquí iría la lógica para enviar el formulario al servidor
};
</script>
<style scoped>
/* ... (estilos existentes) ... */
.error-message {
color: #dc3545;
font-size: 0.875em;
margin-top: 5px;
display: block;
}
input.is-invalid {
border-color: #dc3545;
}
</style>
Explicación de los cambios:
import { Form, Field, ErrorMessage } from 'vee-validate';: Importamos los componentes clave de VeeValidate.import * as yup from 'yup';: Importamos la biblioteca Yup.import { toTypedSchema } from '@vee-validate/yup';: Esta función es crucial para adaptar los esquemas de Yup a VeeValidate.<Form @submit="handleSubmit" :validation-schema="schema">: El componenteFormenvuelve el formulario. La prop@submitsolo se ejecutará si todas las reglas de validación se cumplen. La prop:validation-schemale indica a VeeValidate qué esquema de Yup debe usar para validar.<Field name="username" type="text" id="username" />: El componenteFieldreemplaza a<input>. Es un renderless component por defecto, lo que significa que no renderiza HTML por sí mismo, sino que expone un API. Para que funcione como uninput, podemos pasarle directamente los atributos HTML. La propnamees fundamental, ya que VeeValidate la usa para vincular el campo con su respectivo valor en el esquema de validación y para el manejo del estado.<ErrorMessage name="username" class="error-message" />: Este componente es el encargado de mostrar los mensajes de error asociados a un campo específico (definido por la propname). Se renderiza solo si hay un error de validación para ese campo.schema(objeto Yup): Aquí definimos todas las reglas de validación. Cada propiedad del objetoyup.object()corresponde alnamede un<Field>. Por ejemplo:yup.string().required('mensaje'): El campo debe ser una cadena y es obligatorio..min(3, 'mensaje'): Longitud mínima..email('mensaje'): Debe ser un formato de correo electrónico válido..oneOf([yup.ref('password')], 'mensaje'): Esta es una regla avanzada que asegura que el campoconfirmPasswordsea igual al valor del campopassword.
2. Probando la Validación
Ahora, guarda los cambios y prueba el formulario. Intenta enviarlo vacío, luego con datos incorrectos y finalmente con datos válidos. Verás los mensajes de error aparecer y desaparecer dinámicamente. El evento handleSubmit de la <Form> solo se dispara cuando el formulario es válido.
💡 Estilizando los Mensajes de Error y Campos Inválidos
Para mejorar la experiencia de usuario, es fundamental que los campos inválidos y sus mensajes de error sean visualmente distintivos. VeeValidate no incluye estilos por defecto, pero nos facilita las clases y propiedades para aplicarlos.
1. Añadir Estilos CSS
Ya hemos añadido una clase .error-message en el CSS. También podemos aplicar estilos al input cuando es inválido. VeeValidate puede añadir clases CSS a los campos automáticamente.
Modifica el Field de la siguiente manera para que añada una clase is-invalid si el campo tiene errores:
<Field name="username" type="text" id="username" :class="{'is-invalid': errors.username}" />
<ErrorMessage name="username" class="error-message" />
Esto requiere acceder a los errores del formulario. Para ello, necesitamos la composición useForm o las propiedades de slot del componente Form.
2. Usando la Composición useForm (Recomendado con script setup)
Con script setup, useForm es la forma más directa de acceder a las propiedades de validación. Reemplaza tu script setup existente:
<script setup>
import { Form, Field, ErrorMessage, useForm } from 'vee-validate';
import * as yup from 'yup';
import { toTypedSchema } from '@vee-validate/yup';
const schema = toTypedSchema(
yup.object({
username: yup.string()
.required('El nombre de usuario es obligatorio')
.min(3, 'El nombre de usuario debe tener al menos 3 caracteres')
.max(20, 'El nombre de usuario no puede exceder los 20 caracteres'),
email: yup.string()
.required('El correo electrónico es obligatorio')
.email('Debe ser un correo electrónico válido'),
password: yup.string()
.required('La contraseña es obligatoria')
.min(6, 'La contraseña debe tener al menos 6 caracteres'),
confirmPassword: yup.string()
.required('Confirma tu contraseña')
.oneOf([yup.ref('password')], 'Las contraseñas no coinciden'),
})
);
// Usamos useForm para obtener las funciones y el estado de validación
const { handleSubmit, errors, defineInputBinds } = useForm({
validationSchema: schema,
});
// Podemos usar defineInputBinds para vincular los campos directamente
// const username = defineInputBinds('username');
// <input v-bind="username" :class="{'is-invalid': errors.username}" />
// Sin embargo, usar <Field> es a menudo más conveniente para la mayoría de los casos.
// La función handleSubmit ya está enlazada al useForm
const onSubmit = handleSubmit(values => {
console.log('Formulario enviado y validado:', values);
alert('Registro exitoso! \n' + JSON.stringify(values, null, 2));
// Lógica para enviar el formulario al servidor
});
</script>
Con errors disponible, puedes aplicar condicionalmente la clase is-invalid a tus campos Field (o a los elementos input si no usas Field directamente):
<Field name="username" type="text" id="username" :class="{'is-invalid': errors.username}" />
<ErrorMessage name="username" class="error-message" />
¡Espera! El Field de VeeValidate ya inyecta estas propiedades. No necesitas pasar errors manualmente al Field si usas el slot-scope o la forma v-bind="field" directamente. Sin embargo, para fines de ejemplo, si quisieras usar un input HTML nativo en lugar de Field, errors sería útil.
Para el componente Field, VeeValidate ya añade automáticamente las clases si configuras los props. La forma más sencilla de añadir la clase is-invalid es a través del slot field de <Field>.
<template>
<Form @submit="onSubmit" :validation-schema="schema">
<!-- ... -->
<div class="form-group">
<label for="username">Nombre de Usuario:</label>
<Field name="username" v-slot="{ field, meta }">
<input type="text" id="username" v-bind="field" :class="{'is-invalid': meta.touched && !meta.valid}">
</Field>
<ErrorMessage name="username" class="error-message" />
</div>
<!-- Repite para otros campos -->
<div class="form-group">
<label for="email">Correo Electrónico:</label>
<Field name="email" v-slot="{ field, meta }">
<input type="email" id="email" v-bind="field" :class="{'is-invalid': meta.touched && !meta.valid}">
</Field>
<ErrorMessage name="email" class="error-message" />
</div>
<div class="form-group">
<label for="password">Contraseña:</label>
<Field name="password" v-slot="{ field, meta }">
<input type="password" id="password" v-bind="field" :class="{'is-invalid': meta.touched && !meta.valid}">
</Field>
<ErrorMessage name="password" class="error-message" />
</div>
<div class="form-group">
<label for="confirmPassword">Confirmar Contraseña:</label>
<Field name="confirmPassword" v-slot="{ field, meta }">
<input type="password" id="confirmPassword" v-bind="field" :class="{'is-invalid': meta.touched && !meta.valid}">
</Field>
<ErrorMessage name="confirmPassword" class="error-message" />
</div>
<button type="submit">Registrarse</button>
</Form>
</template>
Aquí, field contiene las propiedades para vincular el input (name, id, value, onInput, onChange, onBlur). meta contiene información sobre el estado de validación del campo (touched, dirty, valid, invalid).
⚙️ Reglas de Validación Personalizadas con Yup
Yup es extremadamente extensible. Puedes añadir tus propias reglas de validación para satisfacer requisitos específicos que no están cubiertos por las reglas predefinidas.
Imaginemos que queremos una regla para asegurarnos de que el nombre de usuario no contenga caracteres especiales, solo letras y números.
1. Extender Yup
Puedes extender Yup en un archivo separado para mantener tu código limpio. Crea un archivo src/utils/yup-extensions.js:
// src/utils/yup-extensions.js
import * as yup from 'yup';
yup.addMethod(yup.string, 'noSpecialChars', function (message) {
return this.test('no-special-chars', message, function (value) {
const { path, createError } = this;
return (
(value === null || value === undefined) || /^[a-zA-Z0-9]+$/.test(value)
) || createError({ path, message });
});
});
// También puedes añadir otras extensiones aquí
// yup.addMethod(yup.string, 'strongPassword', function (message) { /* ... */ });
// Importante: exportar Yup una vez extendido si lo necesitas en otros lugares
export default yup;
2. Usar la Regla Personalizada en el Esquema
Ahora, importa la versión extendida de Yup en tu RegistrationForm.vue y usa la nueva regla noSpecialChars:
<script setup>
import { Form, Field, ErrorMessage, useForm } from 'vee-validate';
// Importamos Yup desde nuestro archivo de extensiones
import * as yup from '@/utils/yup-extensions'; // Asegúrate de que la ruta sea correcta
import { toTypedSchema } from '@vee-validate/yup';
const schema = toTypedSchema(
yup.object({
username: yup.string()
.required('El nombre de usuario es obligatorio')
.min(3, 'El nombre de usuario debe tener al menos 3 caracteres')
.max(20, 'El nombre de usuario no puede exceder los 20 caracteres')
.noSpecialChars('El nombre de usuario solo puede contener letras y números'), // ¡Nuestra nueva regla!
email: yup.string()
.required('El correo electrónico es obligatorio')
.email('Debe ser un correo electrónico válido'),
password: yup.string()
.required('La contraseña es obligatoria')
.min(6, 'La contraseña debe tener al menos 6 caracteres'),
confirmPassword: yup.string()
.required('Confirma tu contraseña')
.oneOf([yup.ref('password')], 'Las contraseñas no coinciden'),
})
);
const { handleSubmit, errors } = useForm({
validationSchema: schema,
});
const onSubmit = handleSubmit(values => {
console.log('Formulario enviado y validado:', values);
alert('Registro exitoso! \n' + JSON.stringify(values, null, 2));
});
</script>
Ahora, si intentas usar caracteres especiales en el nombre de usuario, verás el mensaje de error personalizado.
✍️ Explicación de `yup.addMethod`
La función `yup.addMethod` te permite extender los tipos de esquema existentes (como `yup.string`).
- El primer argumento es el tipo al que quieres añadir el método (`yup.string`).
- El segundo es el nombre de tu nuevo método (`'noSpecialChars'`).
- El tercero es la función que implementa la lógica de validación. Esta función recibe el mensaje de error como argumento.
- Dentro de la función, `this` se refiere al contexto de Yup, lo que te permite acceder a propiedades como `path` (el nombre del campo actual) y `createError` (una función para generar un error).
- El método `test` es la base para las validaciones personalizadas. Recibe un nombre para el test, el mensaje de error y una función que devuelve `true` si es válido, o `false` y llama a `createError` si es inválido.
🔄 Resetear y Recargar Formularios
Después de enviar un formulario exitosamente, es común querer resetearlo a su estado inicial. VeeValidate facilita esto.
1. Usando la Función resetForm
La función resetForm se obtiene del hook useForm. Puedes llamarla después de un envío exitoso.
<script setup>
import { Form, Field, ErrorMessage, useForm } from 'vee-validate';
import * as yup from '@/utils/yup-extensions';
import { toTypedSchema } from '@vee-validate/yup';
const schema = toTypedSchema(
yup.object({
username: yup.string()
.required('El nombre de usuario es obligatorio')
.min(3, 'El nombre de usuario debe tener al menos 3 caracteres')
.max(20, 'El nombre de usuario no puede exceder los 20 caracteres')
.noSpecialChars('El nombre de usuario solo puede contener letras y números'),
email: yup.string()
.required('El correo electrónico es obligatorio')
.email('Debe ser un correo electrónico válido'),
password: yup.string()
.required('La contraseña es obligatoria')
.min(6, 'La contraseña debe tener al menos 6 caracteres'),
confirmPassword: yup.string()
.required('Confirma tu contraseña')
.oneOf([yup.ref('password')], 'Las contraseñas no coinciden'),
})
);
const { handleSubmit, errors, resetForm } = useForm({
validationSchema: schema,
});
const onSubmit = handleSubmit(async (values) => {
console.log('Formulario enviado y validado:', values);
alert('Registro exitoso! \n' + JSON.stringify(values, null, 2));
// Simular un envío asíncrono
await new Promise(resolve => setTimeout(resolve, 1000));
// Resetear el formulario después del envío exitoso
resetForm();
console.log('Formulario reseteado.');
});
</script>
La función resetForm() sin argumentos reseteará todos los campos a sus valores iniciales (o a vacío si no se especificaron valores iniciales). Puedes pasar un objeto para resetear a valores específicos o cambiar el estado dirty o touched.
2. Establecer Valores Iniciales
Si quieres que tu formulario comience con valores, puedes pasarlos a useForm.
const { handleSubmit, errors, resetForm } = useForm({
validationSchema: schema,
initialValues: {
username: 'john.doe',
email: 'john.doe@example.com',
password: '',
confirmPassword: ''
}
});
Ahora, cuando el componente se monte, el formulario se inicializará con estos valores. Al llamar a resetForm(), volverá a estos valores iniciales.
🔍 Explorando la Composition API: useField y useForm Directo
Para escenarios más avanzados o para mayor flexibilidad, VeeValidate ofrece useField y useForm como funciones composables. Esto te permite tener un control más granular sobre los campos y la validación, especialmente útil si no quieres usar los componentes <Form>, <Field> y <ErrorMessage> directamente.
Consideremos un ejemplo donde creamos un campo personalizado o integramos con un componente de UI de terceros.
<template>
<form @submit.prevent="onSubmit" class="custom-form">
<h3>Formulario con useForm y useField</h3>
<div class="form-group">
<label for="name">Nombre Completo:</label>
<input type="text" id="name" v-model="name.value" :class="{'is-invalid': name.meta.touched && !name.meta.valid}">
<span v-if="name.meta.touched && !name.meta.valid" class="error-message">{{ name.errorMessage }}</span>
</div>
<div class="form-group">
<label for="age">Edad:</label>
<input type="number" id="age" v-model.number="age.value" :class="{'is-invalid': age.meta.touched && !age.meta.valid}">
<span v-if="age.meta.touched && !age.meta.valid" class="error-message">{{ age.errorMessage }}</span>
</div>
<button type="submit" :disabled="!meta.valid">Enviar Registro</button>
<button type="button" @click="resetForm">Limpiar</button>
</form>
</template>
<script setup>
import { useForm, useField } from 'vee-validate';
import * as yup from 'yup';
import { toTypedSchema } from '@vee-validate/yup';
const customSchema = toTypedSchema(
yup.object({
name: yup.string()
.required('El nombre es obligatorio')
.min(2, 'El nombre debe tener al menos 2 caracteres'),
age: yup.number()
.required('La edad es obligatoria')
.positive('La edad debe ser un número positivo')
.integer('La edad debe ser un número entero')
.min(18, 'Debes ser mayor de 18 años'),
})
);
const { handleSubmit, resetForm, meta } = useForm({
validationSchema: customSchema,
});
// Registramos cada campo usando useField
const name = useField('name');
const age = useField('age');
// La función de envío del formulario
const onSubmit = handleSubmit(values => {
console.log('Formulario personalizado enviado:', values);
alert('Formulario personalizado enviado! \n' + JSON.stringify(values, null, 2));
});
</script>
<style scoped>
/* Estilos para el formulario personalizado, similar al anterior */
.custom-form {
max-width: 400px;
margin: 30px auto;
padding: 25px;
border: 1px solid #d0d0d0;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
background-color: #fcfcfc;
}
.custom-form h3 {
text-align: center;
color: #444;
margin-bottom: 25px;
}
.custom-form button {
margin-right: 10px;
}
</style>
Explicación:
useForm: Se llama para inicializar el contexto del formulario. Nos devuelvehandleSubmit,resetFormymeta(que contiene el estado general de validez del formulario).useField('name'): Se llama para cada campo individual. Acepta el nombre del campo como argumento. Retorna un objeto reactivo con:value: El valor actual del campo, que se enlaza conv-model.errorMessage: El mensaje de error actual para ese campo.meta: Objeto con el estado del campo (touched,dirty,valid,invalid).
- Enlazando manualmente: En lugar de
<Field>y<ErrorMessage>, ahora vinculamosv-modelafield.value, mostramosfield.errorMessagemanualmente y aplicamos clases condicionalmente usandofield.meta.
Esta aproximación ofrece la máxima flexibilidad, ideal para componentes de UI personalizados o cuando necesitas un control muy específico sobre cómo se renderizan los campos y los errores.
🌍 Internacionalización de Mensajes de Error
Los mensajes de error predeterminados de Yup y VeeValidate están en inglés. Para aplicaciones multilingües, querrás traducirlos. VeeValidate permite configurar un validador para cambiar los mensajes.
1. Configurar un Archivo de Localización
Crea un archivo src/locales/es.js para los mensajes en español:
// src/locales/es.js
import { setLocale } from 'yup';
setLocale({
mixed: {
required: 'Este campo es obligatorio',
oneOf: 'El valor debe ser uno de los siguientes: ${values}',
notOneOf: 'El valor no debe ser uno de los siguientes: ${values}',
notType: ({ path, type, value, originalValue }) => {
// Personaliza aquí si el tipo no coincide
switch (type) {
case 'number':
return `${path} debe ser un número`;
case 'boolean':
return `${path} debe ser un booleano`;
case 'string':
return `${path} debe ser un texto`;
default:
return `Tipo incorrecto para ${path}: se esperaba ${type}, se obtuvo ${typeof value}`;
}
},
},
string: {
min: 'Este campo debe tener al menos ${min} caracteres',
max: 'Este campo no puede exceder los ${max} caracteres',
email: 'Debe ser un correo electrónico válido',
url: 'Debe ser una URL válida',
trim: 'Este campo no debe tener espacios al principio o al final',
lowercase: 'Este campo debe estar en minúsculas',
uppercase: 'Este campo debe estar en mayúsculas',
},
number: {
min: 'Este campo debe ser mayor o igual a ${min}',
max: 'Este campo debe ser menor o igual a ${max}',
lessThan: 'Este campo debe ser menor que ${less}',
moreThan: 'Este campo debe ser mayor que ${more}',
positive: 'Este campo debe ser un número positivo',
negative: 'Este campo debe ser un número negativo',
integer: 'Este campo debe ser un número entero',
},
array: {
min: 'Este campo debe tener al menos ${min} elementos',
max: 'Este campo no puede exceder los ${max} elementos',
},
date: {
min: 'La fecha debe ser posterior a ${min}',
max: 'La fecha debe ser anterior a ${max}',
}
});
2. Importar en main.js o donde sea Global
Para que estos mensajes se apliquen globalmente, importa el archivo de localización en tu main.js:
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import './assets/main.css'; // O tu archivo CSS principal
// Importa tu archivo de localización para Yup
import './locales/es';
createApp(App).mount('#app');
Ahora, los mensajes de error de Yup (y por lo tanto, los de VeeValidate cuando usas validation-schema) deberían aparecer en español.
✅ Conclusión y Próximos Pasos
Has aprendido a implementar un sistema de validación de formularios reactivo y robusto en Vue 3 utilizando VeeValidate y Yup. Hemos cubierto desde la configuración básica hasta la creación de reglas personalizadas y la internacionalización de mensajes de error.
La combinación de VeeValidate y Yup ofrece una solución extremadamente potente y flexible para manejar las complejidades de la validación de formularios, permitiéndote construir aplicaciones más fiables y con una mejor experiencia de usuario.
Puntos Clave Cubiertos:
- 🚀 Configuración de un proyecto Vue 3 con VeeValidate y Yup.
- 📝 Creación de formularios con los componentes
<Form>,<Field>y<ErrorMessage>. - 💡 Definición de esquemas de validación complejos con Yup.
- ⚙️ Creación y uso de reglas de validación personalizadas con
yup.addMethod. - 🔄 Gestión del estado del formulario:
resetFormyinitialValues. - 🔍 Uso de la Composition API (
useForm,useField) para un control más granular. - 🌍 Internacionalización de mensajes de error de Yup.
¿Qué Sigue?
- Validación Asíncrona: Explora cómo realizar validaciones contra un servidor (por ejemplo, comprobar si un nombre de usuario ya existe) con VeeValidate. Puedes integrar funciones asíncronas en tus validaciones de Yup.
- Validación Condicional: Aprende a aplicar reglas de validación solo bajo ciertas condiciones (por ejemplo, un campo es requerido solo si otro tiene un valor específico).
- Componentes de Entrada Personalizados: Crea tus propios componentes de entrada (por ejemplo, un selector de fechas personalizado) y aprende a integrarlos con VeeValidate usando
useField. - Integración con UI Frameworks: Si usas un framework de UI como Vuetify, PrimeVue o Element Plus, explora las integraciones específicas de VeeValidate para estos.
¡Felicidades! Ahora tienes las herramientas para crear formularios complejos y bien validados en tus aplicaciones Vue 3. ¡Sigue experimentando y construyendo!
Tutoriales relacionados
- Controlando la Visibilidad: Directivas v-if, v-show y v-for en Vue 3 para Renderizado Condicional y Listasintermediate15 min
- Migrando de Options API a Composition API en Vue 3: Una Guía Prácticaintermediate15 min
- Desarrollo de Componentes Reutilizables y Extendibles en Vue 3 con Slots y Composablesintermediate20 min
- Navegación Dinámica en Vue Router: Rutas Anidadas y Parámetros Avanzadosintermediate20 min
- Optimización de Rendimiento en Vue.js 3: Estrategias Avanzadas para Aplicaciones Rápidasintermediate15 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!