5

我是 Vue Js 和 Vuelidate 的新手。刚刚尝试验证来自父组件的表单输入字段,如下所示:https ://github.com/monterrail/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".

有任何想法吗?谢谢。

4

4 回答 4

1

我面临着同样的问题。这是我为解决它所做的。

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

<ChildComponent @returnStatusToParent="formStatus =>isChildReady=formStatus"></ChildComponent>

  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", () => `{});`
  }

希望能帮助到你 :)

于 2020-03-28T02:31:59.500 回答
1

在这个问题已经有一个公认的解决方案之后,我正在添加我的答案,但仍然希望它可以帮助其他人。我整个星期都在这。上述解决方案都不适用于我的场景,因为子组件嵌套了 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 中的错误传达给组件本身,但是这种方法可以让我在发生错误时暂停表单提交。

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

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

于 2020-12-18T22:55:37.283 回答
0

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

// 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
      }
   }
于 2019-10-17T21:57:19.233 回答
-2

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

<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())
...
于 2018-12-18T08:52:54.130 回答