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/i18nprimevueeprimeiconstailwindcss(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
