I've written a custom validator like this:
created () {
this.$validator.extend('validateCert', {
getMessage: (field) => {
return field + ' is not a valid certificate';
},
validate: (value) => {
return value.startsWith('-----BEGIN CERTIFICATE-----') && value.endsWith('-----END CERTIFICATE-----');
}
});
}
I've attached it to a text area inside a modal:
<div class="pb-3 mr-4">
<b-form-textarea
type="text"
v-validate="'required|validateCert'"
data-vv-validate-on="change"
v-model.trim="signedCerts[index]"
data-vv-scope="uploadCert"
:name="'certificate_' + index"
:class="[{'is-invalid': errors.has('certificate_' + index)}]"
rows="15"/>
<fr-validation-error :validatorErrors="errors" :fieldName="'certificate_' + index"></fr-validation-error>
</div>
Then - on button click I do the following:
uploadCerts (event) {
let idmInstance = this.getRequestService(),
body = {
fromCSR: true,
certs: _.each(this.signedCerts, (cert) => {
JSON.stringify(cert);
})
};
this.$validator.validateAll('uploadCert').then((valid) => {
// Prevent modal from closing
event.preventDefault();
if (valid) { // some more logic
If I inspect the computed errors object, I will see my failed validation:
{
"items": [
{
"id": "19",
"field": "certificate_0",
"msg": "certificate_0 is not a valid certificate",
"rule": "validateCert",
"scope": "uploadCert",
"regenerate": {
"_custom": {
"type": "function",
"display": "<span>ƒ</span> regenerate()"
}
}
}
]
}
and the value of 'valid' (either true or false) is accurate at all times. I'm just not seeing my error classes being triggered.
Hard to completely answer the question because part of it depends on what happens in fr-validation-error
, but I think the problem is how you're using scopes.
When you define data-vv-scope="uploadCert"
that means that every reference to field-name has to be prefaced by uploadCert.
in errors
. So when you specify in your :class
that errors.has('certificates_'+index)
, you have to change that to errors.has('uploadCert.certificates_'+index)
.
Here's how it would look in full (minus the bootstrap-vue and multiple fields bits):
<textarea
v-validate="'required|validateCert'"
data-vv-validate-on="change"
data-vv-scope="uploadCert"
v-model.trim="signedCert"
name="certificate"
class="form-control"
:class="{ 'is-invalid': errors.has('uploadCert.certificate') }"
rows="10"
>
</textarea>
Full working example for one certificate upload field: https://codesandbox.io/s/z2owy0r2z3