Reputation: 509
I have a simple form with a few inputs to capture contact details. the form can be repeated using the add button provided. the user must select a primary contact if multiple contacts being added. I have a custom validator for this. My problem arises when a couple of rows being added and unselect all primary contact checkboxes then select one. - at this point, I want all errors that are previously shown to be disappeared. for some reason, two way data binding doesn’t seem to work or I must be doing something wrong. assuming I have more validations on other fields, how can I get ride of validation errors related to primary contact checkboxes?
<template>
<div id="app">
<b-col md="12">
<ValidationObserver ref="contactValidation">
<b-row
v-for="(item, index) in contactDtos"
:id="item.id"
:key="item.id"
ref="row"
>
<b-col md="3">
<!-- First Name -->
<b-form-group>
<ValidationProvider
#default="{ errors }"
name="First name"
vid="FirstName"
>
<b-form-input
id="'firstName' + item.id"
v-model="item.firstName"
:state="errors.length > 0 ? false : null"
placeholder="First Name"
/>
<small class="text-danger">{{ errors[0] }}</small>
</ValidationProvider>
</b-form-group>
</b-col>
<b-col md="3">
<!-- Last Name -->
<b-form-group>
<ValidationProvider
#default="{ errors }"
name="Last name"
vid="LastName"
>
<b-form-input
id="'lastName' + item.id"
v-model="item.lastName"
:state="errors.length > 0 ? false : null"
placeholder="Last Name"
/>
<small class="text-danger">{{ errors[0] }}</small>
</ValidationProvider>
</b-form-group>
</b-col>
<b-col md="3" class="mt-2">
<!-- Primary contact -->
<b-form-group>
<ValidationProvider
#default="{ errors }"
:rules="{ chk_primary_contact: [contactDtos, item.id] }"
name="Primary contact"
vid="PrimaryContact"
>
<b-form-checkbox
v-model="item.primaryContact"
:checked="item.primaryContact"
:state="errors.length > 0 ? false : null"
>
Primary contact
</b-form-checkbox>
<small class="text-danger">{{ errors[0] }}</small>
</ValidationProvider>
</b-form-group>
</b-col>
<b-col md="2" class="mt-2">
<b-row>
<b-col v-if="index + 1 == contactDtos.length" cols="6">
<b-button
:v-if="false"
variant="outline-primary"
class="rounded-circle"
@click="contactFormRepeat"
>
Add
</b-button>
</b-col>
<b-col
v-if="index + 1 == contactDtos.length && contactDtos.length > 1"
cols="6"
>
<b-button
variant="outline-danger"
class="rounded-circle"
@click="removeContactForm(index)"
>
Delete
</b-button>
</b-col>
</b-row>
</b-col>
<b-col cols="12">
<hr />
</b-col>
</b-row>
</ValidationObserver>
</b-col>
</div>
</template>
<script>
import { extend, ValidationProvider, ValidationObserver } from "vee-validate";
import {
BRow,
BCol,
BFormGroup,
BFormInput,
BFormCheckbox,
BButton,
// BFormInvalidFeedback,
} from "bootstrap-vue";
export const validatorPrimaryContact = (chkValue, [contactDtos, id]) => {
console.log(id);
if (contactDtos === undefined || id === undefined) return true;
if (chkValue) {
contactDtos.forEach((x) => {
if (x.id !== id) {
// remove if multiple check boxes are checked.
x.primaryContact = false;
}
});
const contactCount = contactDtos.filter((x) => x.primaryContact === true);
if (contactCount.length === 1) {
return true;
}
return false;
} else {
const contactCount = contactDtos.filter((x) => x.primaryContact === true);
if (contactCount.length === 0) {
return false;
} else {
return true;
}
}
};
extend("chk_primary_contact", {
validate: validatorPrimaryContact,
message: "Please select a primary contact",
});
export default {
name: "App",
components: {
ValidationProvider,
ValidationObserver,
BRow,
BCol,
BFormGroup,
BFormInput,
BFormCheckbox,
BButton,
},
data() {
return {
contactDtos: [
{
id: 1,
firstName: "",
LastName: "",
primaryContact: true,
},
],
};
},
methods: {
contactFormRepeat() {
const { length } = this.contactDtos;
this.contactDtos.push({
id: length + 1,
firstName: "",
lastName: "",
contactEmail: "",
contactPhone: "",
primaryContact: false,
});
},
removeContactForm(index) {
this.contactDtos.splice(index, 1);
if (this.contactDtos.length === 1) {
this.contactDtos[0].primaryContact = true;
}
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Please find the sandbox here.
Any help would be highly appreciated!
Upvotes: 0
Views: 1090
Reputation: 99
Did you find a solution for this yet? Since other check boxes other than the one you have clicked are not triggered, how about manually removing errors yourself?
Give checkbox validation provider a ref
and when checkbox is triggered
remove other checkbox errors. Something like this...
template:
<ValidationProvider
:ref="`PrimaryContact${index}`"
#default="{ errors }"
:rules="{ chk_primary_contact: [contactDtos, item.id] }"
name="Primary contact"
vid="PrimaryContact"
>
<b-form-checkbox
v-model="item.primaryContact"
:checked="item.primaryContact"
:state="errors.length > 0 ? false : null"
@change="onChange(index)"
>
Primary contact
</b-form-checkbox>
<small class="text-danger">{{ errors[0] }}</small>
</ValidationProvider>
`methods:
onChange(ref) {
console.info(ref);
for (let i = 0; i < this.contactDtos.length; i++) {
console.info(`i == ${i}`);
if (i !== ref) {
this.$refs[`PrimaryContact${i}`][0].errors = [];
}
}
},
Upvotes: 1