VeeValidateの使い方(Vue + TypeScript + Vuetify)


実施内容

Vue(TypeScript)でVeeValidateを使ったバリデーションを実施したメモです。Vuetifyを使っています。Vueは、Vue.extend方式を使っています。あまり詳しい説明は記載できていません。

動作環境

  • Node.js v12.18.3
  • npm 6.14.8
  • vue-cli 4.5.6
  • vue 2.6.12
  • vuetify 2.2.11

使い方

インストール

npm install --save vee-validate

import

import Vue from 'vue';
import { ValidationProvider, ValidationObserver, extend } from 'vee-validate';
import { required, email } from 'vee-validate/dist/rules';
コンポーネント 用途
ValidationProvider 指定項目でバリデーションを行う
ValidationObserver 複数のバリデーションをグループ化する
extend ルールを編集する

ルールの指定

ルール一覧

sample.vue

// 編集なし(デフォルトのルール・メッセージを使用
extend('email', email);

// デフォルトのメッセージを上書き
extend('required', {
  ...required,
  message: '{_field_}は必須項目です。'
});

{_field_}には、ValidationProviderのname要素が割り当てられる。

メッセージは、上記のように使うルールだけ日本語に書き換える方法と、デフォルトで全て日本語にする方法がある。日本語化については、こちら
デフォルトのメッセージは、以下に記載されている。
英語→node_modules/vee-validate/dist/locale/en.json

componentsに登録

そのまま。

sample.vue
export default Vue.extend({
  name: 'Login',
  components: {
    ValidationProvider,
    ValidationObserver,
  },
  ...

v-text-fieldにバリデーションを追加

v-text-fieldvalidation-providerで囲む。

sample.vue
<validation-provider v-slot="{ errors }" name="User ID" rules="required">
  <v-text-field
    prepend-icon="mdi-account-circle"
    label="User ID"
    v-model="user.userId"
    :error-messages="errors"
  />
</validation-provider>

v-slotで、エラーメッセージなど様々な値を取得する。上記の例では、エラーメッセージを取得し、v-text-fieldのエラーメッセージに入力している。
ルールは複数指定可能。例 rules="required|email"


そのほかにv-slotで取得できる値はこちら

バリデーションのグループ化

この場合、v-formValidationObserverで囲む。

Sample.vue
          <ValidationObserver ref="observer" v-slot="{ invalid }">
            <v-form>
              <v-container>
                <validation-provider v-slot="{ errors }" name="User ID" rules="required">
                  <v-text-field
                    prepend-icon="mdi-account-circle"
                    label="User ID"
                    v-model="user.userId"
                    :error-messages="errors"
                    @input="input"
                  />
                </validation-provider>
                <validation-provider v-slot="{ errors }" name="Password" rules="required">
                  <v-text-field
                    prepend-icon="mdi-account-lock"
                    type="password"
                    label="Password"
                    v-model="user.password"
                    :error-messages="errors"
                  />
                </validation-provider>
              </v-container>
            </v-form>
            <v-btn type="submit" @click="doLogin" :loading="loading" :disabled="invalid">
              ログイン<v-icon>mdi-login</v-icon>
            </v-btn>
          </ValidationObserver>

この状態では、User IdとPassword二つのバリデーションをValidationObserverで確認する。ここでも、v-slotで、エラーメッセージなど様々な値を取得できる。上記の例では、invalidで二つのバリデーションが成功しているか確認し、ログインボタンの有効・無効を制御している(:disabled="invalid"の部分)。したがって、User IdとPassword両方を入力しないと、ボタンが有効化しない。

そのほかにv-slotで取得できる値はこちら

$refsを使ったValidationObserverの制御(引っかかったところ)

vueのmethod内でバリデーションをリセットしたい時などに、$refsを利用してValidationObserver Compornent APIにアクセスすることが必要になる。ここで、Typescriptを使っていると記載方法に癖がある。
公式ドキュメントに記載している方法では、Vue.extendのパターンには合わなかったので、以下の方法で実施した。

Sample.vue
    ...
    resetForm() {
      this.user.userId = '';
      this.user.password = '';
      (this.$refs.observer as InstanceType<typeof ValidationObserver>).reset();
    },

このように記載することで、reset()を使えるようになる。
今回の例だと、

<ValidationObserver ref="observer" v-slot="{ invalid }">

で検出したバリデーションのエラーを

(this.$refs.observer as InstanceType<typeof ValidationObserver>).reset();

でリセットすることになる。

これに時間かかった、、、

日本語化

最後に、メッセージを全て日本語化する。
公式ドキュメント

まず、tsconfig.jsonを編集する。

tsconfig.json
{
  "compilerOptions": {
    // ...
    "resolveJsonModule": true,
    "esModuleInterop": true
    // ...
  }
}

importその2+

localizeと、日本語メッセージが含まれるja.jsonをimportする。また、localizeで日本語を有効化する。

Sample.vue
// localize追加
import { ValidationProvider, ValidationObserver, localize, extend } from 'vee-validate';
// 追加
import ja from 'vee-validate/dist/locale/ja.json';

localize('ja', ja);

日本語のメッセージ一覧→vee-validate/dist/locale/ja.json

以上。