vuelidate async validator - how to debounce?
Asked Answered
Z

2

6

So I have an issue with async validator on my email/user form element. Every time a letter is typed in, it checks for validation. If the email is 30chars, then that is over 30 calls! Anyone know the best way to debounce a vuelidate custom validator? When I try to use debounce, i get all sorts of errors from vuelidate since it's expecting a response.

<div class="form-group">
        <label for="emailAddress">Email address</label>
        <input type="email" class="form-control col-md-6 col-sm-12" v-bind:class="{ 'is-invalid': $v.user.email.$error }" id="emailAddress" v-model.trim="$v.user.email.$model" @change="delayTouch($v.user.email)" aria-describedby="emailHelp" placeholder="[email protected]">
        <small v-if="!$v.user.email.$error" id="emailHelp" class="form-text text-muted">We'll never share your email with anyone.</small>
        <div class="error invalid-feedback" v-if="!$v.user.email.required">Email address is required.</div>
        <div class="error invalid-feedback" v-if="!$v.user.email.email">This is not a valid email address.</div>
        <div class="error invalid-feedback" v-if="!$v.user.email.uniqueEmail">This email already has an account.</div>
    </div>

    <script>
        import { required, sameAs, minLength, maxLength, email } from 'vuelidate/lib/validators'
        import webapi from '../services/WebApiService'
        import api from '../services/ApiService'
    
        const touchMap = new WeakMap();
    
        const uniqueEmail = async (value) => {
            console.log(value);
            if (value === '') return true;
    
            return await api.get('/user/checkEmail/'+value)
                        .then((response) => {
                            console.log(response.data);
                            if (response.data.success !== undefined) {
                                console.log("Email already has an account");
                                return false;
                            }
                            return true;
                        });
        } 
    
        export default {
            name: "Register",
            data() {
              return {
                errorMsg: '',
                showError: false,
                user: {
                  firstName: '',
                  lastName: '',
                  email: '',
                  password: '',
                  password2: ''
                }
              }
            },
            validations: {
                user: {
                    firstName: {
                        required,
                        maxLength: maxLength(64)
                    },
                    lastName: {
                        required,
                        maxLength: maxLength(64)
                    },
                    email: {
                        required,
                        email,
                        uniqueEmail //Custom async validator
                    },
                    password: {
                        required,
                        minLength: minLength(6)
                    },
                    password2: {
                        sameAsPassword: sameAs('password')
                    }
                }
            },
            methods: {           
                onSubmit(user) {
                    console.log(user);
                    /*deleted*/
    
                },
                delayTouch($v) {
                    console.log($v);
                    $v.$reset()
                    if (touchMap.has($v)) {
                        clearTimeout(touchMap.get($v))
                    }
                    touchMap.set($v, setTimeout($v.$touch, 1250))
                }
            }
        }
    </script>

When I try to wrap my async function with the debounce, vuelidate does not like it, so I removed it. Not sure how to limit the custom "uniqueEmail" validator.

Zugzwang answered 19/10, 2018 at 3:42 Comment(2)
github.com/monterail/vuelidate/issues/242Taro
I would also want to know. I do not want to just make the validation always on blur but to limit the requests sent to the backend and keep it dynamic though a little laggyPlesiosaur
B
3

as 'Teddy Markov' said, you could call $v.yourValidation.$touch() on your input blur event. I think it's more efficient way to use Vuelidate.


<input type="email" class="form-control col-md-6 col-sm-12"
           :class="{ 'is-invalid': !$v.user.email.$anyError }"
           id="emailAddress" v-model.trim="$v.user.email.$model"
           @change="delayTouch($v.user.email)"
           @blur="$v.user.email.$touch()"
           aria-describedby="emailHelp"
           placeholder="[email protected]"
>
Beadledom answered 22/4, 2020 at 7:22 Comment(0)
D
0

I found the best way was to combine with regex for emails if regex test passes then proceed to check if unique - else skip the check completely.

Diminished answered 10/9, 2020 at 11:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.