vue.js
VeeValidate

VeeValidateで複数のフィールドにバリデーションをかけるやり方

More than 1 year has passed since last update.

VeeValidateとは?

VeeValidateはVue.jsのバリデーション用プラグイン
Vue.js2.0に対応しており、非常に柔軟なプラグインで、入力フィールドの検証とエラー表示ができます。
検証ルールが豊富にありデフォルトだけで20以上あります。独自ルールも設定可能です。

ドキュメントはこちら
VeeValidate

同時に複数のフィールドを検証するやり方

ドキュメントを読んだのですが、例を見つけることができなかったので
カスタムルールを作成しました。
(一つの項目が複数のフィールドで構成されているような場合)
ドキュメントはES2015/ES6の構文で書かれているので、普段書き慣れていないが書いてみる。

サンプルコード

HTML
<div id="app">
    <label class="label" for="street">Street</label>
    <div>
        <input type="text" name="street" v-model="street">
    </div>
    <label class="label" for="street_number">Street Number</label>
    <div>
        <input type="text" name="number" v-model="number">
    </div>
    <label class="label" for="city">City</label>
    <div>
        <input type="text" name="city" v-model="city">
    </div>

    <div v-show="errors.has('address')">
        <p v-show="errors.firstByRule('address', 'all_not_empty')">{{ errors.first('address') }}</p>
    </div>
</div>

複数のフィールドにv-modelディレクティブを使用し、データバインディングを作成。
errorsオブジェクトを使い、エラーのレンダリングを行います。
has('field')でそのフィールドに関連するエラーがないかどうかをチェックし、エラーがあれば
first('field')でエラーメッセージを表示。

カスタムバリデーション
VeeValidate.Validator.extend('all_not_empty', {
    currentAddress: null,
    getMessage: field => {
        if (!this.currentAddress.street)
            return "Address requires a street";
        if (!this.currentAddress.number)
            return "Address requires a street number";
        if (!this.currentAddress.city)
            return "Address requires a city";
    },
    validate: value => {
        this.currentAddress = value;
        if (!value.street || !value.number || !value.city)
            return false;

        return true;
    }
});

バリデーションにカスタムルールを追加。
全てに入力がなければfalseを返す検証ルールと、
入力がないフィールドに対するエラーメッセージを設定。

Vueインスタンス
new Vue({
    el: '#app',
    data: () => ({
        street:'',
        number: '',
        city: '',
    }),
    created() {
        this.$validator.attach('address', 'all_not_empty');
    },
    computed: {
        address() {
            return {
                street: this.street,
                number: this.number,
                city: this.city
            };
        }
    },
    watch: {
        address(value) {
            this.$validator.validate('address', value);
        }
    }
});

算出プロパティ(computed)にaddressを宣言。
インスタンスが作成された後にaddressに対してカスタムルールall_not_emptyを設定
ウォッチャ(watch)を利用することで、データが変わるのに応じてバリデーションを実行する。

さいごに

複数のフィールドに対するバリデーションの応用はできそうな感じがする。
だけど、カスタムコンポーネント(同時に検証する複数のフィールドを含む)を作成して
カスタムバリデーションを適用するようなやり方がスマートなのかもしれない・・・
もっとスマートなやり方があれば教えてほしいです。