🧐

Vueにフォーム検証機能を実装する (vuelidate)

2021/08/23に公開

概要

  • Vue.jsのフォーム検証機能を実装するため、vuelidateを実装したお話です。

はじめに

  • 話さないこと
    • Vue.jsの導入
    • Vue 3.x での実例紹介
    • カスタムバリデーションの方法
  • 話すこと
    • vuelidateの導入
    • コンポーネントへの実装
    • Vue 2.x での実例紹介

環境

  • Vue.js 2.x
  • Bootstrap 4.x
  • npm ?
    • 当時のバージョンのメモを失念してましたが、13.x だったと思います。
    • 間違っていても最新バージョンで問題はないと思いますが、間違っていたらごめんなさい。

導入

  1. インストール

    npm install vuelidate --save
    
  2. インポート(グローバル設定)

    import Vue from 'vue'
    import Vuelidate from 'vuelidate'
    Vue.use(Vuelidate)
    

コンポーネントに実装

  • $task.name に対して 必須(required)検証をかける

    import { required } from 'vuelidate/lib/validators'
    export default {
        validations: {
            task: {
                name: {
                    required,
                }
            }
        }
    }
    
  • templateに検証結果を反映する

    <input type="text" :value="task.name" :class="{'is-invalid': $v.task.name.$invalid}" />
    <div class="invalid-feedback" v-if="!$v.task.name.required">必須です</div>
    
  • 実装イメージ
    うまくいくとこんな感じになります。
    vuelidate.png

どのように検証しているか?

  • validationsに対し、computedに$vが生成され検証結果をリアクティブに反映してくれます。

    $v: {
        task: {
            name: {
                "required": false,
                "$invalid": true,
                "$dirty": false,
                "$error": false,
            }
        }
    }
    
  • $vのプロパティについて

    Name Description
    $invalid 検証結果がエラーだったらtrue
    $dirty 一度でも入力が行われたらtrue
    $error $invalid$dirtyが共にtrueだったらtrue
  • 入力が行われてから検証を開始したい時(初期表示でエラーにさせたくない)

    • $dirty を使う必要がある。
    • その準備として、$touchInputにバインドする、
      バインドしないと$dirtyは反映されないので注意。
    • また、$invalidではなく$errorに変更します。
    - :class="{'is-invalid': $v.task.name.$invalid}"
    + :class="{'is-invalid': $v.task.name.$error}" @input="$v.task.name.$touch()"
    
    実装イメージ

    vuelidate2.gif

実例紹介

  • 4文字以上の検証を追加する

    - import { required } from 'vuelidate/lib/validators'
    + import { required, minLength } from 'vuelidate/lib/validators'
    export default {
        validations: {
            task: {
                name: {
                    required,
    +               minLength: minLength(4)
                }
            }
        }
    }
    
    実装イメージ

  • すべての検証がOKとなるまで登録ボタンをクリックできないようにする。
    $v.invalidには全ての検証結果が反映されているので、それを利用します。

    <button type="button" @click="onClickStore()" :disabled=$v.$invalid>Store</button>
    
    実装イメージ

さいごに

  • 個人的にフォームバリデーションはUX向上(ユーザーのストレス軽減)に大きく寄与すると感じていますしコスパも良いので、費用にもよりますが積極的に採用しています。
    • (私の現場の業務用アプリではまだまだ2021年現在でも採用されない場合も多いですが、提案はします)
  • VeeValidateも気になっているので、試したらまた記事しようと思います。

参考サイト

Discussion