【问题标题】:Validate form input fields in child component from a parent component with Vuelidate使用 Vuelidate 从父组件验证子组件中的表单输入字段
【发布时间】:2019-05-06 19:05:03
【问题描述】:

我是 Vue Js 和 Vuelidate 的新手。刚刚尝试验证来自父组件的表单输入字段,如下所示:https://github.com/monterail/vuelidate/issues/333

父组件中的子组件:

<contact-list ref="contactList" :contacts="contacts" @primaryChanged="setPrimary" @remove="removeContact" @ready="isReady => readyToSubmit = isReady"/>

子中的方法:

computed: {
    ready() {
        return !this.$v.email.$invalid;
    }
},
watch: {
    ready(val) {
        this.$emit('ready', val);
    }
},

methods: {
    touch() {
        this.$v.email.$touch();
    }
}

我像这样从父级调用 touch() 方法:

submit() {
            this.$refs.contactList.touch();
        },

但我得到这个错误:

Error in event handler for "click": "TypeError: this.$refs.contactList.touch is not a function".

有什么想法吗?谢谢。

【问题讨论】:

  • 似乎没问题。您是否尝试在创建 contact-list 之前调用它?

标签: vue.js vuejs2 vue-component vuelidate


【解决方案1】:

我已经找到了另一种验证的解决方案,它非常简单。父组件中的子组件:

<contact-list ref="customerContacts" :contacts="customer.contacts" />

子组件中的验证:

:validator="$v.model.$each[index].name
...
validations: {
    model: {
        required,
        $each: {
            name: {
                required
            },
            email: {
                required,
                email
            },
            phone: {
                required
            }
        }

    }

}

并在父项中提交:

async onSubmit() {
            if(this.$refs.customerContacts.valid())
...

【讨论】:

  • 抱歉,您能详细解释一下吗?我不明白这个例子。。也许我今天很愚蠢......
  • 能否稍微扩展(并解释)您的代码?
  • 从哪里获得 .valid() 功能?
  • 在子组件中创建一个名为valid的方法,然后让它返回this.$v.$invalid
【解决方案2】:

在父组件上提交表单期间尝试验证子组件时遇到了类似问题。我的子组件只有一层深,所以如果你有更深的嵌套,这种方式可能不起作用,或者你必须递归检查或其他东西。可能有更好的检查方法,但这对我有用。祝你好运。

// parent component
  methods: {
    onSave() {
      let formIsInvalid = this.$children.some(comp => {
        if (comp.$v) { // make sure the child has a validations prop
          return comp.$v.$invalid
        }
      })

      if (!formIsInvalid) {          
        // submit data
      }          
      else {
        // handle invalid form
      }
   }

【讨论】:

    【解决方案3】:

    我也遇到了同样的问题。这是我为解决它所做的。

    1. 创建了一个全局事件池。我可以使用$emit 发出事件,我的孩子可以使用$on$once 订阅并使用$off 取消订阅。在您的app.js 中粘贴以下代码。以下是事件池操作列表。

      • 发射:this.$eventPool.$emit()
      • 开启:this.$eventPool.$on()
      • 关闭:this.$eventPool.$off()
      • 一次:this.$eventPool.$once()

    Vue.prototype.$eventPool = new Vue();

    1. 在我的子组件中,我在$v 上创建了一个watch,如下所示。它将表单的状态发送到父组件。
    watch: {
        "$v.$invalid": function() {
          this.$emit("returnStatusToParent", this.$v.$invalid);
        }
      }
    
    1. 现在在您的父组件内部处理如下状态。

    &lt;ChildComponent @returnStatusToParent="formStatus =&gt;isChildReady=formStatus"&gt;&lt;/ChildComponent&gt;

    1. 现在要向用户显示正确的错误,我们将$touch 子表单。为此,我们需要在上面创建的事件池中发出一个事件,我们的孩子将订阅它。

    父母:

    this.$eventPool.$emit("touchChildForm");

    孩子:

     mounted() {
        this.$eventPool.$on("touchChildForm", () => {
          this.$v.$touch();
          this.$emit("returnStatusToParent", this.$v.$invalid);
        });
      },
      destroyed() {
        this.$eventPool.$off("touchChildForm", () => `{});`
      }
    

    希望对你有帮助:)

    【讨论】:

      【解决方案4】:

      在这个问题已经有一个公认的解决方案之后,我添加了我的答案,但仍然希望它可以帮助其他人。我整个星期都在这。上述解决方案都不适用于我的场景,因为子组件嵌套了 2 层深,因此当我需要最大的父组件来触发所有验证并能够知道表单是否有效时,“ref”方法将不起作用。

      最后,我使用了 vuex 和一个相当简单的消息模块。这是那个模块:

      const state = {
        displayMessages: [],
        validators: []
      };
      
      const getters = {
        getDisplayMessages: state => state.displayMessages,
        getValidators: state => state.validators
      };
      
      const actions = {};
      
      const mutations = {
        addDisplayMessage: (state, message) => state.displayMessages.push(message),
        addValidator: (state, validator) => {
          var index = 0;
          while (index !== -1) {
            index = _.findIndex(state.validators, searchValidator => {
              return (
                searchValidator.name == validator.name &&
                searchValidator.id == validator.id
              );
            });
            if (index !== -1) {
              console.log(state.validators[index]);
              state.validators.splice(index, 1);
            }
          }
      
          state.validators.push(validator);
        }
      };
      
      export default {
        state,
        getters,
        actions,
        mutations
      };
      

      然后每个组件在其挂载事件中都有这个:

        mounted() {
          this.addValidator( {name: "<name>", id: 'Home', validator: this.$v}) ;
        }
      

      现在当用户点击主页上的“提交”按钮时,我可以像这样触发所有验证:

        this.getValidators.forEach( (v) => {
          console.log(v);
          v.validator.$touch();
        });
      

      我可以很容易地检查 vuelidate 对象的 $error, $invalid 属性。根据我的测试,vuelidate 反应性保持不变,因此即使将对象保存到 vuex,组件字段上的任何更改都会按预期反映。

      我打算留下消息和样式以将 gui 中的错误传达给组件本身,但是这种方法可以让我在发生错误时暂停表单提交。

      这是一件好事吗?老实说,我不知道。如果在添加验证器之前必须删除验证器,唯一的问题是。我认为这更多是我的组件逻辑的问题,而不是作为验证解决方案的问题。

      鉴于这花了我整整一周的时间,我对解决方案非常满意,但欢迎任何反馈。

      【讨论】:

        猜你喜欢
        • 2019-06-18
        • 2018-06-07
        • 2018-08-30
        • 2018-01-13
        • 2022-06-11
        • 2020-01-30
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多