Journey

技術に関することと覚書と

VeeValidateで子供のコンポーネントまでvalidateする

※3.0.3が出てるので、できればそちらを使いましょう。

バージョン

  • VeeValidate: 2.2.15 

VeeValidateで下のコードのようなバリデーションを行おうと思ったときにうまく動きませんでした。

<!-- EmailField.vue -->
<template>
  <div>
    <input v-model="user.email" v-validate="'required|email'" name="email">
  </div>
</template>

<script>
export default {
  props: {
    user: {
      type: Object,
      required: true
    }
  }
};
</script>
<!-- App.vue -->
<template>
  <div id="app">
    <form>
      <input v-model="user.name" v-validate="'required'" name="name">
      <email-field :user="user"></email-field>
      <button @click="submit">submit</button>
    </form>
  </div>
</template>

<script>
import EmailField from "./components/EmailField";
export default {
  name: "App",
  components: { EmailField },
  data() {
    return {
      user: {
        name: "",
        email: ""
      }
    };
  },
  methods: {
    submit() {
      this.$validator.validate().then(valid => {
        if (valid) {
          window.console.log("success");
        } else {
          window.console.log("failure");
        }
      });
    }
  }
};
</script>

具体的に何がうまく行かなかったかというとemailが不正な値でもconsoleにsuccessが表示されてしまいました。

どうやら this.$validator.validate() は自分の要素だけを検証してPromiseを返すようです。ということで下のようにして解決しました。

<template>
  <div id="app">
    <form>
      <input v-model="user.name" v-validate="'required'" name="name">
      <email-field :user="user" ref="emailField"></email-field>
      <button @click="submit">submit</button>
    </form>
  </div>
</template>

<script>
import EmailField from "./components/EmailField";
export default {
  name: "App",
  components: { EmailField },
  data() {
    return {
      user: {
        name: "",
        email: ""
      }
    };
  },
  methods: {
    submit() {
      Promise.all([
        this.$validator.validate(),
        this.$refs.emailField.$validator.validate()
      ])
      .then(valid => {
        if (valid.every(e => e)) {
          window.console.log("success");
        } else {
          window.console.log("failure");
        }
      });
    }
  }
};
</script>

<style>
</style>

変更点は <email-field>ref="emailField" をつけたのと、submit() の中身です。

Promise.all() を使用してそれぞれの要素で validate() メソッドを呼びそれらがすべて成功したときのみを成功とすることで正しく処理できました。

書き終わったあとに気づきましたが VeeValidate の version3 出てたので新しく作る場合は新しいものを使いましょう。