如何实现支持Vee-Validate作用域的自定义错误组件?
Great question! Repeating error check logic across form fields gets tedious fast—let's build a reusable component that handles scoped Vee-Validate errors cleanly. Here's a step-by-step implementation tailored to your needs:
Step 1: Define the ErrorForm Component
First, create a reusable component that accepts the required scope, field, errors object, and styling props. It will compute the full scoped field key and expose error state to its slot content.
<template> <div class="form-field-wrapper"> <!-- Scoped slot to pass error state to the input/field --> <slot :has-error="hasError" :error-class="cssClass" ></slot> <!-- Error message display --> <div v-show="hasError" class="help is-danger text-red" > {{ errorMessage }} </div> </div> </template> <script> export default { name: 'ErrorForm', props: { // Required form scope (matches Vee-Validate scope) scope: { type: String, required: true, validator: value => value.trim().length > 0 }, // Field name (matches data-vv-name or v-model field) field: { type: String, required: true, validator: value => value.trim().length > 0 }, // Vee-Validate errors object (from $validator.errors) status: { type: Object, required: true, validator: value => typeof value.has === 'function' && typeof value.first === 'function' }, // CSS class to apply when there's an error cssClass: { type: String, default: 'is-danger' }, // Optional label text (if you want the component to render the label) label: { type: String, default: '' } }, computed: { // Combine scope and field into the full Vee-Validate key fullFieldKey() { return `${this.scope}.${this.field}`; }, // Check if the field has an error hasError() { return this.status.has(this.fullFieldKey); }, // Get the first error message for the field errorMessage() { return this.status.first(this.fullFieldKey); } } }; </script>
Step 2: Use the Component in Your Form
Now you can replace your repetitive error logic with the clean component syntax you wanted. The scoped slot lets you pass the error state directly to your input:
<!-- Your form with Vee-Validate scope --> <form data-vv-scope="form-partner"> <error-form :status="errors" scope="form-partner" css-class="is-danger" field="PartnerName" label="Partner Name" > <template v-slot="{ hasError, errorClass }"> <label>{{ label }}</label> <input v-model="form_fields.name" data-vv-as="Partner name" data-vv-name="PartnerName" v-validate="'required'" :class="{ 'input': true, 'form-control': true, [errorClass]: hasError }" type="text" > </template> </error-form> <!-- Example with BootstrapVue input --> <error-form :status="errors" scope="form-partner" css-class="is-danger" field="CompanyName" label="Company Name" > <template v-slot="{ hasError, errorClass }"> <label>{{ label }}</label> <b-form-input v-model="form_fields.company" data-vv-as="Company name" data-vv-name="CompanyName" v-validate="'required'" :class="[errorClass, hasError ? errorClass : '']" type="text" ></b-form-input> </template> </error-form> <button @click="onSubmit('form-partner')">Submit</button> </form>
Step 3: Update Your Submit Method (Optional)
If you want to validate only the specific scope instead of all forms, adjust your submit method to target the scope:
methods: { onSubmit(scope) { this.$validator.validateAll(scope).then(result => { if (result) { alert('Form Submitted!'); } }); } }
Key Notes
- Scope Enforcement: The component uses prop validation to ensure a non-empty scope is always provided, preventing mistakes.
- Flexibility: Scoped slots let you use any input component (native, BootstrapVue, custom) while still leveraging the error state.
- Consistency: All error display logic is centralized, so updating styles or error behavior only needs to be done once in the component.
This implementation eliminates repetitive error checking code while fully supporting Vee-Validate's scoped validation.
内容的提问来源于stack exchange,提问作者Rasik

