Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom async vue-validator breaks validation component

I'm trying to perform asynchronous validation for one of my Vue.js components using vue-validator, following this example. I'd like to check if the email provided by a user is already taken.

This is the validator implementation I'm currently struggling with:

Vue.validator('emailUnique', {
    message: 'this e-mail address has already been taken',
    check: function (val) {
        return Vue.http({
            url: '/validate/email-unique',
            method: 'POST',
            data: {
                email: val
            }
        }).then(
            function (response) { // success
                console.log('success');
                return Promise.resolve();
            },
            function (response) { // error
                console.log('error');
                return Promise.reject();
            }
        ).catch(function(error) {
            console.log('catch');
            return Promise.reject();
        });
    }
});

Which I use in my component like so:

<div>
<validator name="userValidator">
  <form novalidate class="form-group" v-on:submit.prevent="submitUser">
    <div class="form-group">
      <label for="email">E-Mail</label>
        <input id="email" name="email" type="email" class="form-control"
               placeholder="[email protected]"
               v-model="user.email" required v-validate:email="{ required: true, email: true, emailUnique: true }">
        <div class="form-validation-error" v-if="$userValidator.email.required && $userValidator.email.touched">
          <span>this field is required</span>
        </div>
        <div class="form-validation-error" v-if="$userValidator.email.email && $userValidator.email.touched">
          <span>not a valid e-mail address</span>
        </div>
        <div class="form-validation-error" v-if="$userValidator.email.emailUnique && $userValidator.email.touched">
          <span>this e-mail address has already been taken</span>
        </div>
    </div>
  </form>
</validator>
</div>

Unfortunately, this breaks the entire validation object for email:

[Vue warn]: Error when evaluating expression "$userValidator.email.required && $userValidator.email.touched".
TypeError: scope.$userValidator.email is undefined

If I don't register the emailUnique validator, the other two validation rules work fine. Also, the request to /validate/email-unique is posted correctly and receives the expected return value (just a json_encoded response with true/false), and I see the corresponding console.log() output ('success', 'error', 'catch'), so I'm guessing the return value for the check function isn't correct and causes vue-validator to fail.

Vue.http does return a Promise though, so according to the docs and the example linked to above this should be fine. I also tried to return true or false from within the .then() clause, yet Vue.http still returns a Promise (which apparently troubles vue-validator -- maybe the Promise object I'm returning is not of the form vue-validator expects?).

Any tipps on this?

like image 821
falloutghst Avatar asked Dec 12 '25 09:12

falloutghst


1 Answers

Does this problem persist if you turn vue.config.debug to false? There is an issue where Vue tries to evaluate scope.$userValidator.email.required BEFORE vue-validator actually creates that variable. This only flags an error during debug mode and works otherwise. The variable will EVENTUALLY exist and work, just not at the time it's initially evaluated. This is an issue with the lifecycle of the directive that will require some tweaks to vue core.

See here: https://github.com/vuejs/vue-validator/issues/99

I do not believe this issue has been resolved that I know of. You may try upgrading Vue and vue-validator to the latest versions if you haven't already. I know @kazupon, creator of vue-validator has a contribution in vue 1.0.19 that relates to this, though not sure if it was fixed: https://github.com/vuejs/vue/releases/tag/v1.0.19

edit: this is fixed in new versions. vue 1.0.19 added support for terminal directives. From the docs:

Vue compiles templates by recursively walking the DOM tree. However when it encounters a terminal directive, it will stop walking that element’s children.

In short, Vue will no longer try to compile the elements inside a validator, and will leave it to the plugin. Make sure you have validator 2.0.0, which was released just a couple days after the vue core update: https://github.com/vuejs/vue-validator/releases/tag/v2.0.0

like image 156
Jeff Avatar answered Dec 15 '25 21:12

Jeff



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!