logaretm / vee-validate

✅ Painless Vue forms
https://vee-validate.logaretm.com/v4
MIT License
10.82k stars 1.27k forks source link

Validator.extend bug or no? #608

Closed danielsalles closed 7 years ago

danielsalles commented 7 years ago

Versions:

Description:

I'm trying to do an email check in the database and vee just understands it as if it was true. The variable data.exist is returning correctly from the database (true or false).

Steps To Reproduce:

Validator.extend('verify_email',{
        getMessage: field => 'Esse e-mail já é cadastrado.',
        validate: value => http.post('user/email_exist', { email: value })
                           .then(({ data }) => !!data.exist)
        })
logaretm commented 7 years ago

Promises should resolve with an object containing valid property, so you can just do this:

Validator.extend('verify_email',{
        getMessage: field => 'Esse e-mail já é cadastrado.',
        validate: value => http.post('user/email_exist', { email: value })
                           .then(({ data }) => ({ valid: !!data.exist }))
        })
danielsalles commented 7 years ago

Same thing. Regardless of whether the data.exist is true or false, the result is the same:

Image of Yaktocat

    Validator.extend('verify_email',{
        getMessage: field => 'Esse e-mail já é cadastrado.',
        validate: value => http.post('user/email_exist', { email: value })
                           .then(({ data }) => {
                            console.log('data.exist', !!data.exist)
                            return { valid: !!data.exist }
                            })
        })

PS: I added console.log() to facilitate debugging. PS2: I do not have the slightest idea of what might be happening :/.

logaretm commented 7 years ago

OK, I've created a small example for you:

https://jsfiddle.net/logaretm/m4ro7927/

I'm using rc.6 in that example, I noticed you said you are using beta.14 which is a very old version and might have had bugs or missing features.

axieum commented 7 years ago

I'm trying the exact same thing, been trying all day doing email/username in the same function though. But all should still work, my issue is almost identical in terms of the console outputting the correct true/false value of the response, but Vue just refuses to update the input validity.

This is my HTML for the input, basic styling and just the Instagram regex for usernames.

<input name="username" :class="{'is-danger': errors.has('username'), 'is-success': fields.username &amp;&amp; fields.username.valid}" v-validate="{rules:{required: true, min: 2, max: 16, regex: /^(?!\_)(?!.*\.\.)(?!.*\_\_)(?!.*\_$)(?!.*\.$)[^\W][\w.]{1,15}$/, exists: 'username'}}" class="input" type="text" placeholder="Username" value="{{ old('username') }}"  required autofocus>

Here is how I configured my custom rule for the checking if a username/email already exists. I am attempting to throttle the checks, as I only wish to check for existence after they've stopped typing for a few seconds, not sure how to do that though (I tried lodash's throttle method), anyway:

const throttledChecks = {};
const existsRule = {
    getMessage(field) {
        'That ' + field + ' is already in use.'
    },
    validate(value, [type]) {
        if (!value || !type) {
            return false;
        }
        const key = type + '|' + value;
        if (! throttledChecks[key]) {
            throttledChecks[key] = _.throttle(function() {
                return axios.post('/register/check/' + type, {value: value})
                    .then(function (response) {
                        return response.data.valid;
                    }).catch(function (error) {
                        console.log(error);
                    });
            }, 500, {leading: true, trailing: false});
        }
        return throttledChecks[key]();
    }
};
VeeValidate.Validator.extend('exists', existsRule);

Literally outputs to the console the correct true/false from the request, but VeeValidate/Vue doesn't want to update the styling to be is-danger.

logaretm commented 7 years ago

@Axiom1999 You need to return an object in your promises, not plain true and false values, your objects need to have valid property that is either true or false. from what I can see in your code, you are returning boolean values directly.

return {
  valid: response.data.valid
};

styling may be caused by another issue though, it will be helpful if you try to inspect the errorBag after validation.

On a side note, it might be helpful to return Booleans directly in promises, so this can be seen as an enhancement here.