【问题标题】:Validate child input components on submit with Vee-Validate使用 Vee-Validate 在提交时验证子输入组件
【发布时间】:2017-04-22 17:16:16
【问题描述】:

我目前正在尝试创建一个包含多个“输入字段”组件的注册表单,一旦按下提交,这些组件都需要验证。当其中的文本发生更改时,它们目前都自行验证,但我发现很难对所有输入字段进行全局调用以验证所有内容。我想要实现的是:http://vee-validate.logaretm.com/examples#validate-form 但 validateAll() 方法没有附加任何字段。

我尝试使用 email 和 confirm_email 填充 validateAll(),这得到了我想要的结果,但错误消息不会显示在字段旁边。

任何帮助将不胜感激!

ValidatedInputField.vue:

<template>
   <div class="form-control" v-bind:class="{ errorPrompt : errors.has(name) }">
      <label v-bind:for="name">* {{as}}</label>
      <input ref="input" v-bind:value="_value" @input="updateValue($event.target.value)" v-validate v-bind:data-vv-rules="rules" v-bind:name="name" />
      <span v-bind:v-show="'errors.has(' + name +')'">{{ errors.first(name) }}</span>
   </div>
</template>

<script>
module.exports = {
  props: ['name', 'rules', 'as', 'value'],
  methods: {
  updateValue(value) {
     this._value = this.value;
     this.$emit('input', value);
  }
  },
  computed: {
     _value() { return this.value; }
  }
};
</script>

注册.vue:

<template>
  <div class="container">
    <Card blueHeader="true" title="Register">
      <ValidatedInputField v-model="email" name="email" rules="required|email" as="Email" />
      <ValidatedInputField v-model="confirm_email" name="confirm_email" rules="required|email" as="Confirm Email" />
      <ValidatedInputField name="company" rules="required" as="Company" />
      <InputField name="company_website" as="Company Website" />
      <ValidatedInputField name="first_name" rules="required" as="First Name" />
      <ValidatedInputField name="last_name" rules="required" as="Last Name" />
      <ValidatedInputField name="address_1" rules="required" as="Address 1" />
      <InputField name="address_2" as="Address 2" />
      <ValidatedInputField name="city" rules="required" as="City" />
      <ValidatedInputField name="zip" rules="required" as="Zip/Postal Code" />
    </Card>

    <Card blueHeader="true" title="Terms & Conditions">
      <button v-on:click="submitForm()">Submit</button>
    </Card>
  </div>
</template>

<script>
import ValidatedInputField from './components/ValidatedInputField';
import InputField from './components/InputField';

module.exports = {
  methods: {
    submitForm() {
      this.$validator.validateAll();
    }
  },
  data() {
    return {
      email: '',
      confirm_email: ''
    };
  },
  components: {
    ValidatedInputField,
    InputField
  }
};
</script>

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    我有类似的设置,我尝试了带有事件的总线解决方案,但没有得到它的工作。然而,我使用了 v-validate 规范中定义的 Provider/Injector 模式。

    所以在最顶层的父级中,添加这行代码(注意它是 TYPESCRIPT !)

     @Provide('validator') $validator = this.$validator;
    

    并且在每个子/孙子中添加这行代码:

    @Inject('validator') $validator: any;
    

    现在您可以在您的父级中执行此操作,我将使用验证器注入器从所有组件中收集所有错误。 (见规格:https://baianat.github.io/vee-validate/api/errorbag.html#api

     if (this.$validator.errors.any()) {
          // Prevent the form from submitting
          e.preventDefault();
        }
    

    我在帖子中有一个类似的答案; vee-validate error object - _vm.errors is undefined

    grtz

    【讨论】:

    • 优秀的答案。投票赞成。很难找到关于 vuejs+typescript 的帮助资源。如果你有什么好的,请告诉我。
    • 嘿@AntonK,我现在才看到你的这个评论,关于 vue 与 typescript 结合的资源确实不多,但这里有一些我们关注的 repos:github.com/vuejs/awesome-vue 和 @987654324 @ .. 我们正在将我们的项目迁移到 vue cli 以保持领先于所有新的开发(也将您的项目迁移到 webpack 4/typescript > 2.9),我们渴望等待 VUE 3,它将是 typescript 原生的 :-)
    • @antonK ,当您遇到特定问题时,您可以在我的简历中找到很多我的社交,您也可以直接与我联系 :-D
    • 这里是在 vee-validate baianat.github.io/vee-validate/concepts/… 中提供/注入的 API 文档
    【解决方案2】:

    我不确定我是否理解正确。但是要在全局范围内进行调用,您必须在单击按钮时发出一个事件,并指示每个模板对该事件采取行动。每个模板的操作应该是 'this.$validator.validateAll()',因为 'this' 将引用该特定模板。

    您可以通过创建命名实例(“总线”)来做到这一点。在创建实例之前创建它。

    var bus = new Vue({});
    

    使用它从模板发出:

    bus.$emit('validate_all');
    

    并在模板中捕获:

    created: function() {
       var vm = this;
       bus.$on('validate_all', function() {
          vm.$validator.validateAll()
       });
    }
    

    现在应该已经验证了所有字段并且应该显示所有错误消息。 祝你好运!

    【讨论】:

    • 适用于 Vuejs 2 和 VeeValidate 2。
    • 很好的解释@hugo-wijdeveld!但是如何在父组件中进行提交,因为它没有子错误对象?
    • 基本上我会通过让组件发出并让主实例捕获来处理这个问题。例如:您可以让组件发出一个布尔值,指示有或没有任何错误。然后主实例可以决定是否可以提交。但是您可以更加详细并发出完整的错误对象,以便主实例可以向用户提示错误发生的位置。
    • 另一种方法是让父节点直接调用子节点验证器,而不使用事件总线。这里的答案提供了该解决方案:stackoverflow.com/a/43472878/398513
    • 这可能有帮助medium.com/@logaretm/…
    【解决方案3】:

    对于普通的 Vuejs,我使用:

    inject: ['$validator'],
    

    在孩子身上,

    和:

    provide() {
       return {
         $validator: this.$validator,
       };
    },
    

    在父级中。

    【讨论】:

    • 像魅力一样工作。
    【解决方案4】:

    我正在使用不同的验证器库。我没有听说过 vee-validate,但它看起来很简洁,我可能会切换,因为它支持 Vue 2.0,而 vue-validator 现在不支持。不过,它们在概念上看起来非常相似。

    假设您没有使用 Vuex,并且这是一个小应用程序,您可以使用计算属性来获取每个子项的验证状态:

    家长:

    isValid: function () { 
        for (var i = 0; i < this.$children.length; i++) {
          if (this.$children[i].hasOwnProperty('isValid') && !this.$children[i].isValid) {
            return false
          }
        }
        return true
      }
    

    孩子:

      isValid: function () {
        return this.$vueValidator.valid
      }
    

    如果您有一个不想被验证的孩子,请不要给它一个 isValid 计算属性。

    您也可以 $emit 一个来自孩子的事件,当他们将状态从无效 -> 有效或有效 -> 无效时告诉父母。

    【讨论】:

      【解决方案5】:

      就我而言,我所做的是禁用vee-validate 注入:

      Vue.use(VeeValidate, { inject: false });
      

      这将使插件停止为每个组件实例实例化一个新的验证器范围, 不包括根实例。

      在父组件中,我得到一个新的验证器实例,我将与所需的子组件共享:

      export default {
        $_veeValidate: {
            validator: 'new' // Determines how the component get its validator instance
                             // 'new' means it will always instantiate its own validator instance
        },
        ......
      

      在子组件中,我注入父的验证器实例:

      export default {
          // This will make the component inherit it's parent's validator scope,
          // thus sharing all errors and validation state. Meaning it has access
          // to the same errors and fields computed properties as well.
          inject: ['$validator'],
          ...........
      

      资源:https://baianat.github.io/vee-validate/concepts/components.html

      【讨论】:

        【解决方案6】:

        在提交表单之前,我必须使用承诺来检查验证。

        @ChalkyJoe 原始问题的以下代码

        module.exports = {
          methods: {
            submitForm() {
              //this.$validator.validateAll();
              this.$validator.validateAll().then((result)=>{
                  if(!result){
                    error();
                  }
                  submit();
              })
            }
          },
          data() {
            return {
              email: '',
              confirm_email: ''
            };
          },
        

        【讨论】:

        • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
        猜你喜欢
        • 2017-09-04
        • 1970-01-01
        • 1970-01-01
        • 2020-01-30
        • 2018-03-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-06
        • 2020-12-20
        相关资源
        最近更新 更多