Vee-validate在<b-form-input>标签中验证失效问题排查
b-form-input Hey there! Let's break down why your BootstrapVue b-form-input isn't triggering VeeValidate's required validation, while regular <input> tags work fine. This is a common gotcha with custom form components—here's what's going on and how to fix it:
The Core Issue
VeeValidate works seamlessly with native HTML inputs out of the box because it listens to standard events like input or change and reads the value property directly. But components like b-form-input are wrapped custom components, which might:
- Use custom event names instead of native ones (e.g.,
update:modelValuein Vue 3 instead ofinput) - Hide the underlying native input's value/state from VeeValidate's default listeners
- Require explicit configuration to let VeeValidate know how to interact with them
Common Fixes by Vue/VeeValidate Version
1. Vue 2 + BootstrapVue + VeeValidate 3
If you're using this stack, try these steps:
Add a Name Attribute & Manual Validation Trigger
First, make sure your b-form-input has a unique name (or data-vv-name for VeeValidate 3) and manually trigger validation on its input event:
<b-form-input v-model="middlename" v-validate="'required'" data-vv-name="middlename" name="middlename" @input="$validator.validate('middlename')" ></b-form-input>
Register b-form-input with VeeValidate
For a more permanent fix, register the component with VeeValidate so it knows how to handle it automatically. Add this to your main.js or component's created hook:
import { Validator } from 'vee-validate'; // Register the custom component Validator.registerComponent('b-form-input', { getValue: (component) => component.value, // How to get the component's value events: ['input'] // Which event triggers value changes });
2. Vue 3 + BootstrapVue Next + VeeValidate 4
VeeValidate 4 uses a composition API approach, so the fix is a bit different:
Use useField for Direct Field Control
Bind your b-form-input to a VeeValidate field directly, which handles validation automatically:
<template> <b-form-input v-model="middlename" :state="meta.valid ? 'valid' : meta.invalid ? 'invalid' : null" ></b-form-input> <!-- Show error message if validation fails --> <p class="text-danger" v-if="meta.error">{{ meta.error }}</p> </template> <script setup> import { useField } from 'vee-validate'; // Associate the field with the "required" rule const { value: middlename, meta, errorMessage } = useField('middlename', 'required'); </script>
Or Use the Form Component Wrapper
If you prefer using a form wrapper, ensure your b-form-input has a name and rules attribute:
<template> <Form @submit="handleSubmit"> <b-form-input v-model="middlename" name="middlename" rules="required" ></b-form-input> <!-- Display error --> <ErrorMessage name="middlename" class="text-danger" /> <b-button type="submit">Submit</b-button> </Form> </template> <script setup> import { Form, ErrorMessage } from 'vee-validate'; const middlename = ref(''); const handleSubmit = (values) => { // Handle valid submission console.log(values); }; </script>
Quick Checklist to Rule Out Simple Mistakes
- Did you add a unique
nameattribute to yourb-form-input? VeeValidate needs this to track the field. - Is your
v-modelbinding correctly set up for themiddlenamedata property/ref? - Did you spell the validation rule correctly (
required—no typos!)?
内容的提问来源于stack exchange,提问作者Ashwini

