Nuxt.js + BuefyでVeeValidateを使う方法(2020年版)


はじめに

Nuxt.jsでバリデーションを行う必要があって少し調べたところ、どうやらVeeValidateを使うのが現代の主流らしいようでした。
ところがいざ実装してみると、新旧様々な情報が錯綜していて、とても苦労しました。

公式ドキュメントのサンプルはVue.js向けに書かれているので、Nuxt.jsでの効率的な書き方がなかなか分からなかったのも辛かったです。
いろいろと試行錯誤するはめになってしまいましたが、ようやく良さそうな書き方が分かってきました。
この記事は現時点(2020年初頭)における、Nuxt.js上でVeeValidateを使用する方法のまとめです。

VeeValidateを使うメリット

VeeValidateを使うと、下図のようなバリデーションを簡単に実現できるようになります。
一般的にバリデーションを自分で実装する場合、エラーのパターンに応じたメッセージを準備して、すべてのパターンに対してエラーの判定とメッセージの表示処理を行う必要があり、かなり面倒な作業をする必要があります。
VeeValidateにはバリデーションでよく使う機能が標準で用意されているため、自分で実装する場合に比べてかなりの作業を省略することができます。
多国籍対応済なので、日本語も問題なく使えます。

この記事ではUIコンポーネントにBuefyを使用していますが、ほかのUIコンポーネントでも応用できます。

バージョン情報

  • Nuxt.js 2.10.2
  • vee-validate 3.2.1
  • nuxt-buefy 0.3.19
    • Buefy 0.8.8

導入方法

Nuxtアプリケーションの作り方は省略します。まずは、vee-validateをインストールします。

yarnの場合

yarn add vee-validate

npmの場合

npm i vee-validate --save

プラグインの作成

共通処理を1か所にまとめるため、plugins配下に以下のファイルを作ります。

vee-validate.js
import Vue from 'vue'
import { ValidationProvider, ValidationObserver, localize, extend } from 'vee-validate' // 使用する機能
import ja from 'vee-validate/dist/locale/ja.json' // エラーメッセージの日本語化用
import { required, max, email, min } from 'vee-validate/dist/rules' // 使用するバリデーションルール

// VeeValidateがデフォルトで用意している各ルールを使用するよう指定
extend('required', required) // 必須項目のバリデーション
extend('email', email) // emailのバリデーション
extend('max', max) // 最大文字数のバリデーション
extend('min', min) // 最小文字数のバリデーション

Vue.component('ValidationProvider', ValidationProvider)
Vue.component('ValidationObserver', ValidationObserver)

localize('ja', ja)

この例では4種類のバリデーションルール(必須項目、メールアドレス、最大文字数、最小文字数)を指定しています。
ほかにどんなルールがあるかはこちらを御覧ください。

nuxt.config.jsの修正

先ほど作ったプラグインをアプリケーションから利用できるようにnuxt.config.jsを修正します。

nuxt.config.js
export default {
// 中略
  plugins: [
    "~/plugins/vee-validate"
  ],
// 中略
  build: {
    transpile: [
      "vee-validate/dist/rules"
    ],
// 中略
  }
}

transpileの記述は環境によっては省略できるという情報もありましたが、私の環境では省略するとエラーになりました。

ページコンポーネント

サンプルとして、メールアドレスとパスワードでログインするページを作ってみます。

sample.vue
<template>
  <section>
    <ValidationObserver ref="observer" v-slot="{ passes }">
      <div class="hero is-primary">
        <div class="hero-body">
          <div class="container">
            <h1 class="title">ログイン</h1>
          </div>
        </div>
      </div>
      <div class="container">
        <div class="box">
          <p>バリデーションのサンプル用です</p>
          <ValidationProvider rules="required|email" name="メールアドレス" v-slot="{ errors, valid }">
            <b-field label="メールアドレス" :type="{'is-danger': errors[0], 'is-success': valid }" :message="errors">
              <b-input type="email" v-model="email" placeholder="[email protected]" >
              </b-input>
            </b-field>
          </ValidationProvider>
          <ValidationProvider rules="required|min:8" name="パスワード" v-slot="{ errors, valid }">
            <b-field label="パスワード" :type="{'is-danger': errors[0], 'is-success': valid }" :message="errors">
              <b-input type="password" v-model="password" >
              </b-input>
            </b-field>
          </ValidationProvider>
          <b-button @click="passes(login)">ログイン</b-button>
          <b-button @click="resetForm">リセット</b-button>
        </div>
      </div>
    </ValidationObserver>
  </section>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      password: '',
    }
  },
  methods: {
    login() {
      console.log('Login!')
    },
    resetForm() {
      console.log('Reset!')
      this.email = ''
      this.password = ''
      this.$refs.observer.reset();
    }
  }
 }
</script>

解説

ValidationProviderの使い方

メールアドレスのバリデーション部分を抜粋します。

<ValidationProvider rules="required|email" name="メールアドレス" v-slot="{ errors, valid }">
  <b-field label="メールアドレス" :type="{'is-danger': errors[0], 'is-success': valid }" :message="errors">
    <b-input type="email" v-model="email" placeholder="[email protected]" >
    </b-input>
  </b-field>
</ValidationProvider>

このようにバリデーションを行いたい箇所をValidationProviderで囲みます。
rulesにバリデーションの種類を記載します。パイプでつないで複数指定することができます。
またnameを省略するとエラーメッセージの主語が変数名(この場合は「email」)になります。

いくつかの記事では<validation-provider>のようにケバブケースで記述すると書かれていましたが、実際にやってみるとエラーになりました。公式ドキュメントのサンプルもこのようなキャメルケースになっています。

b-fieldb-inputはBuefy独自のタグなので、ほかのUIを使う場合は気をつけてください。
公式のこのページにほかのUIフレームワークと組み合わせる場合のサンプルが載っています。

バリデーションエラーの場合はこのように表示されます。

バリデーションが通るとこのようになります。

ValidationObserverの使い方

ValidationProviderはエラーメッセージの表示はしてくれますが、Submitを止める機能はありません。
バリデーションエラーが発生しているときはログイン処理を止めたいですよね。
それを実現するのがValidationObserverです。

<ValidationObserver ref="observer" v-slot="{ passes }">
中略(ValidationProviderを含む記述)
</ValidationObserver>

このように、対象となるValidationProviderを含む箇所全体をValidationObserverで囲みます。

バリデーションが通ったときだけlogin処理が呼ばれるようにするには次のように記述します。

<b-button @click="passes(login)">ログイン</b-button>

バリデーションエラーが起きているときにログインボタンをクリックしても、コンソールログが出力されないことを確認してください。

また、バリデーションを初期化するには次のように記述します。

this.$refs.observer.reset();

リセットボタンをクリックしたときに呼ばれているので確認してみてください。

参考URL