Como Validar Formulários com Vee-Validate no Nuxt 3 (sem usar Yup ou Zod)
Neste tutorial, vou te mostrar como integrar o vee-validate
no Nuxt 3 para validar formulários de forma simples, sem depender do Yup ou Zod. O foco será em uma abordagem prática, usando regras de validação declarativas ("required"
, "numeric"
, etc.).
Além disso, usamos componentes do PrimeVue como InputText
, Select
, Button
, Message
e Toast
para criar a interface do formulário com um visual profissional e moderno.
🔧 Pré-requisitos
Antes de começar, certifique-se de que você já tem um projeto Nuxt 3 com:
vee-validate
@vee-validate/rules
@vee-validate/i18n
primevue
eprimeicons
tailwindcss
(opcional, mas usado nos estilos deste exemplo)
📦 1. Instalação
yarn add vee-validate @vee-validate/rules @vee-validate/i18n
⚙️ 2. Criando o Plugin veeValidate.ts
// plugins/veeValidate.ts import { defineRule, configure } from 'vee-validate' import { required, email, numeric, image } from '@vee-validate/rules' import { localize, setLocale } from '@vee-validate/i18n' import ptBR from '@vee-validate/i18n/dist/locale/pt_BR.json' export default defineNuxtPlugin(() => { defineRule('required', required) defineRule('email', email) defineRule('numeric', numeric) defineRule('image', image) configure({ generateMessage: localize({ pt_BR: ptBR }), validateOnInput: false, validateOnBlur: false, validateOnModelUpdate: false, }) setLocale('pt_BR') })
🧩 3. Configurando o Formulário com useForm + defineField
const { defineField, validate, errors } = useForm({ validationSchema: { label: 'required', url: 'required', tipo: 'required', ordem: 'required|numeric', }, }) const form = ref({ label: defineField('label', { label: 'Label' })[0], url: defineField('url', { label: 'Url' })[0], tipo: defineField('tipo', { label: 'Tipo' })[0], ordem: defineField('ordem', { label: 'Ordem' })[0], })
🧪 4. Validando e Submetendo o Formulário
const submitForm = async () => { const validateForm = await validate() if (!validateForm.valid) return // enviar dados para API ou salvar }
💬 5. Exibindo Mensagens de Erro
No template, você pode exibir erros assim:
<Message v-if="errors.label" severity="error">{{ errors.label }}</Message>
<template> <div class="p-6 max-w-3xl mx-auto"> <Toast /> <LoadingComponent v-if="loading" /> <h2 class="text-2xl font-bold mb-4">Novo Registro</h2> <form class="space-y-4" @submit.prevent="submitForm"> <div> <label class="block font-medium">Label</label> <InputText v-model="form.label" placeholder="Nome do Registro" class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary" /> <Message v-if="errors.label" size="small" severity="error" variant="simple" >{{ errors.label }}</Message > </div> <div> <label class="block font-medium">URL</label> <InputText v-model="form.url" placeholder="/url-de-acesso" class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary" /> <Message v-if="errors.url" size="small" severity="error" variant="simple" >{{ errors.url }}</Message > </div> <div> <label class="block font-medium">Tipo</label> <Select v-model="form.tipo" :options="tipo" option-label="name" option-value="value" placeholder="Selecione um Tipo" class="w-full px-4 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary" /> <Message v-if="errors.tipo" size="small" severity="error" variant="simple" >{{ errors.tipo }}</Message > </div> <div> <label class="block font-medium">Ordem</label> <InputText v-model="form.ordem" placeholder="De um numero de ordenação exp: 1" type="number" class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary" /> <Message v-if="errors.ordem" size="small" severity="error" variant="simple" >{{ errors.ordem }}</Message > </div> <Button class="bg-primary hover:opacity-90 transition border-none" label="Salvar Registro" type="submit" /> </form> </div> </template>
🖱️ 6. Quando tentar submeter o formulário será validado e mostrará as mensagens de acordo com as regras definidas
✅ Resultado:
Você vai ter um formulário com:
- Regras de validação simples e legíveis
- Mensagens localizadas em português
- Sem dependências extras
- Total controle sobre o comportamento de validação
nuxt3
vee-validate
validação
primevue
formulário
vuejs
javascript
frontend