Vuex で フォームのバリデーションを実装するにはデータバインディングを使わない方がいい

データバインディングに依存したフォームのバリデーションは非同期な処理が入ったり、他のフォームのフィールドにアクセスする必要があると途端にコードが複雑になってしまうのでどうしたものかと試行錯誤した結果、データバインディングを使わなければコードもシンプルかつ低負荷な実装ができるという結論に至った。

フォームに送信するまではバリデーションを行わず、フォームを送信後はリアルタイムにバリデーションを行う例で考えてみる。

.vue 側はこのように書く。


<template>
...
<input type="text" class="form-control"
               :value="form.params.username.value"
               @keyup.stop="update(
                    value: $event.target.value,
                    )”
<span v-if=“form.params.username.error.length > 0”>{{form.params.username.error}}</span>

<button @click=“submit”>submit</button>
...
</template>

<script>

export default {

    methods: {
        update(value){
            this.$store.dispatch(‘updateUserName',value)
        },
        submit(){
            this.$store.dispatch(‘submit’);
        }
    }
}


</script>

上のコードは input タグが文字入力を受け付けるたびに updateUserName というメソッドに input タグの値を引数にして呼び出している。v-model を使用していないのがポイント。

Vuex 側はこのように書く。



state: {
    form: {
        submitted: false,
        params: {
            username: {
                value: ‘’,
                error: ''
            }
        }
    }
}

mutations: {
    validateUserName(state,field){
        if (field.value.trim().length === 0){
            field.error = 'ユーザー名を入力してください’;
        }else{
            field.error = ‘';
        }
    },
    updateUserName(state,payloads){
        // username をセット
        state.params.username.value = payloads.value;
        // submit がまだの時はバリデーションを行わない
        if (!state.submitted){
            return;
        }
        // username のバリデーションを行う
        this.commit(‘validateUserName’,state.params.username);
    },
    submit(state){
        state.submitted = true;
        this.commit(‘validateUserName’,state.form.params.username);
        if (state.form.params.usernname.error === '’){
            // success!
        }else{
            // validation error.
        }
    }
},

actions: {
    udpateUserName(value){
        const payloads = {value};
        if (value.trim().length === 0){
            this.$store.commit(‘updateUserName',payloads);
        }
    },
    submit(){
       this.$store.commit('submit');
    }
}


Vuex 側では 2つの処理を行なっている。

(1) username の値が変化すると, username のバリデーションを行い、username に値をセット。
(2) submit が呼ばれると, submitted フラグを有効にして username のバリデーションを行なっている。

データバインディングを使ったバリデーションよりも処理の流れが細やかに制御することができるし、処理内容も明確になった。

Related Contents

Pickup Contents