Async validation (custom rule) - not preventing form submission
See original GitHub issueVersions:
- VueJs: 2.1.3
- Vee-Validate: vee-validate@2.0.0-beta.17
I have created a custom rule that uses Ajax to check if the same title already exists (title must be unique). The problem is: when this validation fails - the form is not prevented from being submitted.
I have defined the following custom rule in resources/assets/js/app.js:
require('./bootstrap');
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
import { Validator } from 'vee-validate';
const checkUnique = {
getMessage(field) {
return `Such ${field} already exists.`
},
validate(value) {
if(value) {
return Vue.http.get('api/todos/exists', {params: { title: value }}).then(function (response) {
return {
valid: response.data.valid
}
})
} else {
return false;
}
}
};
Validator.extend('check-unique', checkUnique);
import store from './store'
Vue.component('todos-list', require('./components/todos/TodoList.vue'));
Vue.component('todos-add', require('./components/todos/TodoAdd.vue'));
const app = new Vue({
el: '#app',
store
});
As you can see, this rule uses Ajax (vue-resource) to check if the same title already exists in the database (title must be unique).
In my component’s template (resources/assets/js/components/todos/TodoAdd.vue) I have applied this rule:
<template id="todos-add-template">
<div>
<form @submit.prevent="addTodo" autocomplete="off">
<div class="form-group">
<input name="title" v-validate data-vv-rules="required|check-unique" :class="{'input': true, 'is-danger': errors.has('title') }" v-model="newTodo.title" class="form-control" placeholder="Add a new Todo">
<span v-show="errors.has('title')" class="help is-danger">{{ errors.first('title') }}</span>
</div>
<div class="form-group">
<button class="btn btn-success">Add Todo</button>
</div>
</form>
</div>
</template>
<script>
export default {
template: '#todos-add-template',
data() {
return {
newTodo: { id: null, title: '', completed: false }
}
},
methods: {
addTodo(e) {
this.$validator.validateAll();
if (this.errors.any()) {
e.preventDefault();
} else {
this.$store.dispatch('addTodo', this.newTodo.title);
this.newTodo = { id: null, title: '', completed: false }
}
}
}
}
</script>
<style>
.input.is-danger, .textarea.is-danger {
border-color: #ff3860;
}
.help.is-danger {
color: #ff3860;
}
</style>
As you can see - I prevent form submission:
<form @submit.prevent="addTodo" autocomplete="off">
…
methods: {
addTodo(e) {
this.$validator.validateAll();
if (this.errors.any()) {
e.preventDefault();
} else {
this.$store.dispatch('addTodo', this.newTodo.title);
this.newTodo = { id: null, title: '', completed: false }
}
}
}
And if works fine with rules that are not Async (custom), but when this rule (check-unique
) fails - it only prevents form from being submitted for the first click on the form’s submit button… BUT if I keep clicking on the submit button - at one moment the form will be submitted.
Issue Analytics
- State:
- Created 7 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
I think the issue is here:
this.$validator.validateAll()
, this evaluates immediately and allows the errors check to fail since it has not yet received the result. and it might conflict with next calls depending on when the promise actually finishes.validateAll
returns a promise so you can successfully evaluate the result:To take advantage of this you need to do this:
btw one of your screenshots has 500 error, so something might be wrong on your server.
I guess its not properly documented yet, as I’m planning to reject the promise if the result is false to make it more natural and consistent with other libraries and APIs, so you would put the success handler in
then
and the fail handler incatch
.