VeeValidateを使ってバリデーションをつくる

はじめに

VeeValidateを使ってバリデーションをつくる方法について

VeeValidateをインストール

$ yarn add vee-validate

VeeValidateの設定ファイルを作成

$ touch app/javascript/plugins/veevalidate.js

上記のファイルをインクルードします。

javascript/packs/hello_vue.js

...
...
import '../plugins/veevalidate'
...
...

VeeValidateの設定

先程作成したplugins/veevalidate.jsファイルに設定を書きます

javascript/plugins/veevalidate.js

import Vue from 'vue'

import { extend, ValidationProvider, ValidationObserver } from 'vee-validate';

// 使用するバリデーションのルールをインポート
import { required, email, confirmed, min } from 'vee-validate/dist/rules';

// インポートしたルールのエラーメッセージを日本語にする
extend('required', {
  ...required,
  message: "{_field_}は必須項目です"
});

extend('email', {
  ...email,
  message: "{_field_}の形式で入力してください"
});

extend('confirmed', {
  ...confirmed,
  message: "パスワードと一致しません"
});

extend('min', {
  ...min,
  params: ['length'],
  message: "{_field_}は{length}文字以上で入力してください"
});


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

バリデーションをフォームに設定

ユーザー登録フォーム

<template>
  <div
    id="register-form"
    class="container w-50 text-center"
  >
    <div class="h3 mb-3">
      ユーザー登録
    </div>

    // フォーム全体をvalidation-observeで囲む
    // handleSubmitを使ってフォーム送信前にバリデーションを自動で実行する
    <validation-observer v-slot="{ handleSubmit }">
      <div class="form-group text-left">
        <label for="name">ユーザー名</label>

        // 各フォームをvalidation-providerで囲む
        <validation-provider
          v-slot="{ errors }"   // エラーメッセージを格納する
          name="ユーザー名"
          rules="required"  // 使用するバリデーションルールを指定する
        >
          <input
            id="name"
            v-model="user.name"
            type="text"
            class="form-control"
            placeholder="username"
          >
          <p class="text-danger">
            {{ errors[0] }}   // 格納したエラーメッセージを表示する
          </p>
        </validation-provider>
      </div>
      <div class="form-group text-left">
        <label for="email">メールアドレス</label>
        <validation-provider
          v-slot="{ errors }"
          name="メールアドレス"
          rules="required|email"
        >
          <input
            id="email"
            v-model="user.email"
            type="email"
            class="form-control"
            placeholder="test@example.com"
          >
          <p class="text-danger">
            {{ errors[0] }}
          </p>
        </validation-provider>
      </div>
      <div class="form-group text-left">
        <label for="password">パスワード</label>
        <validation-provider
          v-slot="{ errors }"
          name="パスワード"
          rules="required"
          vid="password"  // vidを指定
        >
          <input
            id="password"
            v-model="user.password"
            type="password"
            class="form-control"
            placeholder="password"
          >
          <p class="text-danger">
            {{ errors[0] }}
          </p>
        </validation-provider>
      </div>
      <div class="form-group text-left">
        <label for="password_confirmation">パスワード(確認)</label>
        <validation-provider
          v-slot="{ errors }"
          name="パスワード(確認)"
          rules="required|min:3|confirmed:password"  //  vidで指定したフォームの入力内容を取得
        >
          <input
            id="password_confirmation"
            v-model="user.password_confirmation"
            type="password"
            class="form-control"
            placeholder="password"
          >
          <p class="text-danger">
            {{ errors[0] }}
          </p>
        </validation-provider>
      </div>
      <button
        type="submit"
        class="btn btn-primary"
        @click="handleSubmit(register)"  // handleSubmitでフォーム送信前にバリデーションをチェック
      >
        登録
      </button>
    </validation-observer>
  </div>
</template>

<script>
export default {
  name: "RegisterIndex",
  data() {
    return {
      user: {
        name: '',
        email: '',
        password: '',
        password_confirmation: '',
      }
    }
  },
  methods: {
    register() {
      this.$axios.post('users', { user: this.user })
        .then(res => {
          this.$router.push({ name: 'LoginIndex' })
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
}
</script>

<style scoped>
</style>