I'm currently trying to create a Registration form with multiple "Input Field" components which all require validating once Submit has been pressed. They all currently validate on their own accord when the text within is changed but I'm finding it difficult to make a global call to all input fields to validate all. What I am trying to achieve is the following: http://vee-validate.logaretm.com/examples#validate-form but the validateAll() method has no fields attached to it.
I tried populating validateAll() with email & confirm_email which got me the result I wanted, but the error messages would not show next to the fields.
Any help would be much appreciated!
ValidatedInputField.vue:
<template>
<div class="form-control" v-bind:class="{ errorPrompt : errors.has(name) }">
<label v-bind:for="name">* {{as}}</label>
<input ref="input" v-bind:value="_value" @input="updateValue($event.target.value)" v-validate v-bind:data-vv-rules="rules" v-bind:name="name" />
<span v-bind:v-show="'errors.has(' + name +')'">{{ errors.first(name) }}</span>
</div>
</template>
<script>
module.exports = {
props: ['name', 'rules', 'as', 'value'],
methods: {
updateValue(value) {
this._value = this.value;
this.$emit('input', value);
}
},
computed: {
_value() { return this.value; }
}
};
</script>
Register.vue:
<template>
<div class="container">
<Card blueHeader="true" title="Register">
<ValidatedInputField v-model="email" name="email" rules="required|email" as="Email" />
<ValidatedInputField v-model="confirm_email" name="confirm_email" rules="required|email" as="Confirm Email" />
<ValidatedInputField name="company" rules="required" as="Company" />
<InputField name="company_website" as="Company Website" />
<ValidatedInputField name="first_name" rules="required" as="First Name" />
<ValidatedInputField name="last_name" rules="required" as="Last Name" />
<ValidatedInputField name="address_1" rules="required" as="Address 1" />
<InputField name="address_2" as="Address 2" />
<ValidatedInputField name="city" rules="required" as="City" />
<ValidatedInputField name="zip" rules="required" as="Zip/Postal Code" />
</Card>
<Card blueHeader="true" title="Terms & Conditions">
<button v-on:click="submitForm()">Submit</button>
</Card>
</div>
</template>
<script>
import ValidatedInputField from './components/ValidatedInputField';
import InputField from './components/InputField';
module.exports = {
methods: {
submitForm() {
this.$validator.validateAll();
}
},
data() {
return {
email: '',
confirm_email: ''
};
},
components: {
ValidatedInputField,
InputField
}
};
</script>
For plain Vuejs i use:
in the child,
and:
in the parent.
I'm using a different validator library. I haven't heard of vee-validate, but it looks neat and I might switch since it supports Vue 2.0 whereas vue-validator does not right now. They look pretty similar in concepts though.
Assuming you're not using Vuex and this is a small app, you could use a computed property to grab the validation status of each of the children:
Parent:
Child:
If you have a child that you don't want to be validated just don't give it an
isValid
computed property.You could also
$emit
an event from a child when they change states from invalid -> valid or valid -> invalid to tell the parent.I'm not sure I understand you correctly. But to make the call globally, you will have to emit an event on clicking the button and instruct each template to act upon that event. The action for each template should be to 'this.$validator.validateAll()', because 'this' will refer to that specific template.
You can do that by creating a named instance ('bus'). Create that before creating the instance.
Use that to emit from the template:
and to catch in a template:
Now all fields should have been validated and all error messages should show. Good Luck!
In my case what I do is that I that I disable
vee-validate
injection:And in the parent component i get a new validator instance which i'll share with the desired childs:
In the child component i inject that parent's validator instance:
Resource: https://baianat.github.io/vee-validate/concepts/components.html
I have a similar setup, I tried the bus solution with the events, didn't get it working. I however used the Provider/Injector pattern as defined in the specs of v-validate.
So in the top most parent, add this line of code (mind it is TYPESCRIPT !)
And in every child/grandchilds add this line of code:
Now you can do this in your parent, and I will gather all errors from all components with the validator injector. (see specs: https://baianat.github.io/vee-validate/api/errorbag.html#api)
I have a sort-a-like answer in post; vee-validate error object - _vm.errors is undefined
grtz