VeeValidateでバリデーション

①vee-validateをインストール。
$ yarn add vee-validate


②pluginsディレクトリ配下にファイルを作成してインスタンスに登録する。
$ touch app/javascript/plugins/veevalidate.js


javascript/packs/hello_vue.js

import '../plugins/veevalidate'


③veevalidateファイルにバリデーションルールを定義する。
import Vue from 'vue'

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

// よくあるルールはすでに用意されているのでインポートして使う。
import {
  email,
  required
} from 'vee-validate/dist/rules';

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

// インポートしたルールを定義。
extend('email', {
  ...email,
  message: '{_field_}の形式で入力してください'
});

extend('required', {
  ...required,
  message: '{_field_}は必須項目です'
});

// もちろん独自ルールも定義できる。
// valueは入力される値。入力される値とは別に引数を取ることもできる。
extend('min', {
  validate(value, { length }) {
    return value.length >= length;
  },
  params: ['length'],
  message: '{_field_}は{length}文字以上で入力してください'
});

extend('max', {
  validate(value, { length }) {
    return value.length <= length;
  },
  params: ['length'],
  message: '{_field_}は{length}文字以下で入力してください'
});

extend('password_confirmed', {
  params: ['target'],
  validate(value, { target }) {
    return value === target;
  },
  message: 'パスワードと一致しません'
});


④定義したルールをフォームで使う。

新規登録時フォーム

<template>
  <div
    id="register-form"
    class="container w-50 text-center"
  >
    <div class="h3 mb-3">
      ユーザー登録
    </div>
    <!-- 該当フォーム全体をValidationObserverで囲む。
          handleSubmitでフォーム送信前にもバリデーションチェックできる。 -->
    <ValidationObserver v-slot="{ handleSubmit }">
      <div class="form-group text-left">
        <!-- 各入力欄をValidationProviderで囲む。
              errorsにエラーメッセージを格納し、rulesで定義したルールを使う。-->
        <ValidationProvider
          v-slot="{ errors }"
          rules="required"
        >
          <label for="name">ユーザー名</label>
          <input
            id="name"
            v-model="user.name"
            name="ユーザー名"
            type="text"
            placeholder="username"
            class="form-control"
          >
          <!-- errorsに格納されたエラーメッセージを表示する。 -->
          <span class="text-danger">{{ errors[0] }}</span>
        </ValidationProvider>
      </div>
      <div class="form-group text-left">
        <ValidationProvider
          v-slot="{ errors }"
          rules="required|email"
        >
          <label for="email">メールアドレス</label>
          <input
            id="email"
            v-model="user.email"
            name="メールアドレス"
            type="email"
            placeholder="test@example.com"
            class="form-control"
          >
          <span class="text-danger">{{ errors[0] }}</span>
        </ValidationProvider>
      </div>
      <div class="form-group text-left">
        <!-- @passwordで入力された値を取得できる。 -->
        <ValidationProvider
          v-slot="{ errors }"
          rules="required"
          vid="password"
        >
          <label for="password">パスワード</label>
          <input
            id="password"
            v-model="user.password"
            name="パスワード"
            type="password"
            placeholder="password"
            class="form-control"
          >
          <span class="text-danger">{{ errors[0] }}</span>
        </ValidationProvider>
      </div>
      <div class="form-group text-left">
        <!-- @passwordでパスワード入力欄で入力された値を取得している。 -->
        <ValidationProvider
          v-slot="{ errors }"
          rules="required|min:3|password_confirmed:@password"
        >
          <label for="password_confirmation">パスワード(確認)</label>
          <input
            id="password_confirmation"
            v-model="user.password_confirmation"
            name="パスワード(確認)"
            type="password"
            placeholder="password"
            class="form-control"
          >
          <span class="text-danger">{{ errors[0] }}</span>
        </ValidationProvider>
      </div>
      <!-- handleSubmitでフォーム送信前にもバリデーションチェックできる。 -->
      <button
        type="submit"
        class="btn btn-primary"
        @click="handleSubmit(register)"
      >
        登録
      </button>
    </ValidationObserver>
  </div>
</template>

タスク作成フォーム

<template>
  <div id="task-create-modal">
    <div
      class="modal"
      @click.self="handleCloseModal"
    >
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-body">
            <ValidationObserver v-slot="{ handleSubmit }">
              <div class="from-group mb-3">
                <ValidationProvider
                  v-slot="{ errors }"
                  rules="required|max:50"
                >
                  <label for="title">タイトル</label>
                  <input
                    id="title"
                    v-model="task.title"
                    name="タイトル"
                    type="text"
                    class="form-control"
                  >
                  <span class="text-danger">{{ errors[0] }}</span>
                </ValidationProvider>
              </div>
              <div class="from-group mb-3">
                <ValidationProvider
                  v-slot="{ errors }"
                  rules="max:500"
                >
                  <label for="description">説明文</label>
                  <textarea
                    id="description"
                    v-model="task.description"
                    name="説明文"
                    class="form-control"
                    rows="5"
                  />
                  <span class="text-danger">{{ errors[0] }}</span>
                </ValidationProvider>
              </div>
              <div class="form-group mb-3">
                <ValidationProvider
                  v-slot="{ errors }"
                  rules="required"
                >
                  <label for="status">ステータス</label>
                  <select
                    id="status"
                    v-model="task.status"
                    name="ステータス"
                    class="form-control"
                  >
                    <option value="todo">
                      TODO
                    </option>
                    <option value="doing">
                      DOING
                    </option>
                    <option value="done">
                      DONE
                    </option>
                  </select>
                  <span class="text-danger">{{ errors[0] }}</span>
                </ValidationProvider>
              </div>
              <div class="d-flex justify-content-between">
                <button
                  type="button"
                  class="btn btn-success"
                  @click="handleSubmit(createTask)"
                >
                  追加
                </button>
                <button
                  type="button"
                  class="btn btn-secondary"
                  @click="handleCloseModal"
                >
                  閉じる
                </button>
              </div>
            </ValidationObserver>
          </div>
        </div>
      </div>
    </div>
    <div class="modal-backdrop show" />
  </div>
</template>



VeeValidate公式:
Basics | VeeValidate
Available Rules | VeeValidate
Handling Forms | VeeValidate