VeeValidate3:自定义验证在提交时始终为真

Posted

技术标签:

【中文标题】VeeValidate3:自定义验证在提交时始终为真【英文标题】:VeeValidate3: Custom validation always is true on submit 【发布时间】:2020-12-21 01:21:57 【问题描述】:

我正在使用 Vue.js 2 和 VeeValidate3 来验证我的表单。这来自也进行 axios 调用以检查用户名是否已在使用中。如果是这样,显然验证需要是false

到目前为止一切顺利。当我输入已在使用的用户名时,我还会看到错误消息 Dieser Name wird bereits verwendet

但是,如果我看到错误消息但仍然单击提交按钮,则错误消息会消失,我可以看到消息 Submit submitCompleteNormalRegistrationForm 在提交表单时打印出来。

问题是,为什么表单提交时名称也存在验证错误?我做错了什么?

另外,当名称不使用时,如何将名称的验证设置为true

这是我目前的代码:

<template>
    <div>
        <ValidationObserver ref="completeNormalRegistrationForm" v-slot=" passes " class="flex-column flex-grow-1 d-flex w-100">
            <form @submit.prevent="passes(submitCompleteNormalRegistrationForm)" id="completeNormalRegistrationForm" class="flex-column flex-grow-1 d-flex w-100">
                <div class="backButtonWrapper text-left">
                    <i id="backButtonRegistrationForm" @click="showLoginForm" class="far fa-arrow-alt-circle-left"></i>
                </div>
                <div class="form-wrapper margin-auto w-100">
                    <p class="rubik-bold" style="font-size: 1rem;">Registrieren</p>
                    <ValidationProvider vid="name" name="Nutzername" rules="required|alpha_dash" v-slot=" errors ">
                        <input @keyup="completeNormalRegistrationFormUsernameExists" class="form-control search-username" v-model="registerForm.name" type="text" placeholder="Username">
                        <span v-if="errors[0]" class="username-invalid-span"> errors[0] </span>
                    </ValidationProvider>
                    <ValidationProvider vid="email" name="E-Mail" rules="required|email" v-slot=" errors ">
                        <input class="form-control search-email" v-model="registerForm.email" type="email" placeholder="E-Mail">
                        <span v-if="errors[0]" class="email-invalid-span"> errors[0] </span>
                    </ValidationProvider>
                    <ValidationProvider vid="confirmation" name="Passwort" v-slot=" errors ">
                        <input class="form-control" v-model="registerForm.password" type="password" placeholder="Passwort">
                        <span v-if="errors[0]" class="password-invalid-span"> errors[0] </span>
                    </ValidationProvider>
                    <ValidationProvider rules="confirmed:confirmation" name="Passwort" v-slot=" errors ">
                        <input class="form-control" v-model="registerForm.passwordConfirmation" type="password" placeholder="Passwort wiederholen">
                        <span v-if="errors[0]" class="password-invalid-span"> errors[0] </span>
                    </ValidationProvider>

                    <button type="submit" class="btn btn-primary btn-big big-letter-spacing text-uppercase rubik-bold login">Anmelden</button>
                </div>
            </form>
        </ValidationObserver>
    </div>
</template>

<script>
    export default 
        name: "NavbarAction",
        data() 
            return 
                registerForm: 
                    name: '',
                    email: '',
                    password: '',
                    passwordConfirmation: '',
                    termsAndConditions: false,
                ,
            
        ,
        methods: 
            async completeNormalRegistrationFormUsernameExists() 
                const nameValid = await this.usernameExists(this.registerForm.name);

                if (nameValid) 
                    this.$refs.completeNormalRegistrationForm.setErrors(name: 'Dieser Name wird bereits verwendet');
                 else 
                    console.log('Set name is NOT in use!');
                
            ,
            async usernameExists(name)
                return await axios.post(window.routes.usernameExists, value: name)
                    .then(r => 
                        return r.data;
                    );
            ,
            submitCompleteNormalRegistrationForm()
                console.log('Submit submitCompleteNormalRegistrationForm');
                console.log(this);
            
        
    
</script>

更新(现在使用自定义规则):

extend('unique-email', (value) => 
    return axios.post(this.routes.emailExists,  value: value )
        .then((r) => 

            // If email exists, axios response is true
            if(r.data)
                return 
                    valid: false,
                    data:  message: 'E-Mail wird bereits genutzt' 
                ;
            else
                return 
                    valid: true,
                ;
            
        , (err) => 
            return 
                valid: false,
                data:  message: 'E-Mail wird bereits genutzt' 
            ;
        )
    ,
)

【问题讨论】:

【参考方案1】:

您需要将您的电子邮件验证器表示为 vee-validate 规则,而不是尝试自己在 keyup 上进行。 vee-validate 中许多未记录的事情之一是,如果您返回一个 Promise 作为验证的结果,vee-validate 将正确处理它,在允许验证通过之前等待获得结果。

下面是一个帮助您入门的示例:

 mounted() 
   extend('unique-email', (value) => 
     return this.usernameExists(value)
     .then((res) => 
      return 
        valid: true,
      ;
    , (err) => 
      this.$refs.completeNormalRegistrationForm.setErrors(
         name: ['Username already registered']
      );
    )
    , 
     immediate: false
   )
 

【讨论】:

谢谢!我目前也在这一点上。我目前的问题是正确设置错误消息。我是否也可以向规则本身添加自定义消息,而不是像您那样使用 $ref 另外,immediate 是什么? 我在上面的问题中添加了我现在卡住的规则! 我相信setErrors 是他们允许您这样做的唯一方法...请参阅here。 好的,谢谢...但是你能告诉我 immediate 是做什么的吗?我已经阅读了文档,但我不明白...【参考方案2】:

这是前端验证。您唯一能做的就是在表单无效时禁用按钮。无论如何,没有什么能阻止聪明的孩子尝试提交表格。真正的验证应该在服务器端。

类似:

<button type="submit" class="btn btn-primary btn-big big-letter-spacing text-uppercase rubik-bold login" :disabled="passes(submitCompleteNormalRegistrationForm)">Anmelden</button>

【讨论】:

还有一个验证服务器端。但我不想每次按键都使用axios...这只是为了限制axios 请求的数量并立即向用户显示错误!【参考方案3】:

终于也找到了不使用$refs设置自定义错误信息的方法:

extend('unique-email', (value) => 
    return axios.post(window.laravel.emailExists,  value: value )
        .then((r) => 

            // If email exists, axios response is true
            if(r.data)
                return "E-Mail wird bereits genutzt";
            else
                return true;
            
        , (err) => 
            return "E-Mail wird bereits genutzt";
        )
    ,
);

【讨论】:

以上是关于VeeValidate3:自定义验证在提交时始终为真的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 提交时触发表单验证

jQuery 自定义标签验证

自定义 HTML5 表单验证最初不显示自定义错误

我如何验证猫鼬自定义验证器中的类型

自定义密码强度验证器插件

自定义单选按钮jqgrid编辑表单