VeeValidate を使って、vue.jsで簡単にバリデートしてみた

現在、vue.jsを使って色々と作っているのですが、フォームでのバリデーションで便利なVeeValidateというライブラリを使ってみました。

## 環境情報

- Vue.js 2.5.13
- VeeValidate 1.0.0

## 事前準備
現在、Rails + webpacker + Vue.jsで開発を行なっています。
そのため、yarnを使ってVeeValidateを導入しました。
`yarn add vee-validate`

そしたら、VeeValidateを読み込む！

```javascript:app.js
import VeeValidate, { Validator } from 'vee-validate'
```
これで、事前準備は完了！

## 基本的な使い方
VeeValidateはhtmlタグの中に、決まり文句を書くだけで、バリデートの設定をしてくれます。

```html:form.vue
<div class="form-group">
   <label for="form_title">タイトル</label>
   <input type="text" name="app[title]" class="form-control"
          v-model="app.title"
          data-vv-as="タイトル"
          v-validate="'required|max:255'"
         :class="{'input': true, 'form-danger': 
         errors.has('app[title]') }"
   />
   <div class="form-control-feedback" v-show="errors.has('app[title]')">
     <p class="alert alert-danger">{{ errors.first('app[title]') }}</p>
   </div>
</div>
```

雛形はこんな感じになります。

### バリデートルールの指定
基本的に、inputタグの中に色々書き込むだけです。
`v-validate`の中にバリデートのルールを書き込みます。

|ルール|意味|
|:---|:---:|
|required|必須|
|max|最大文字数|
|numeric|半角数値のみ|
|email|メールアドレス形式|

よく使うのは、この辺りでしょうか。`v-validate = "required"`と書き込むだけで、必須項目としてルールを追加できます。複数の条件を指定したい場合は`|`で区切ればOK！

### エラーメッセージの表示
指定したルールを満たさない場合は、errors.has('inputのname')の中のフラグがtrueとなります。なので、それを活用して、`v-show="errors.has('app[title]')"`とすれば、
値が入ってないときは、メッセージを非表示、空の時メッセージ表示となります。
また、エラーメッセージはerros.first('inputのname')にあるので、
`{{ errors.first('app[title]') }}`でエラーメッセージが表示されます。

ただ、このままでは、エラーメッセージが
*The app[title] field is required.*
と表示されてしまうので、エラーメッセージを日本語に変えたいです。

### エラーメッセージを日本語化する

```javascript:app.js
// 日本語ファイルを読み込み
import ja from 'vee-validate/dist/locale/ja'

// vee-validateの日本語
Validator.localize('ja', ja);
Vue.use(VeeValidate, { locale: ja });
```

上記のように書き込めば日本語化されます。
*app[title]は必須項目です*
まだ、field名がキモいのでinputタグに直接field名を記述します。
` data-vv-as="タイトル"`と書き込めば、OK

![title.gif](https://qiita-image-store.s3.amazonaws.com/0/148823/c1b7329b-7cac-c8f1-5281-b94f5f36e4cf.gif)

こんな感じでスマートに動きます。

### 特殊なバリデート
よく使うと思うのですが、フォーム中で、ある条件の中だけ必須項目にしたいみたいなこともあると思います。

```html:app.vue
<div class="form-group">
  <label>投票締切</label>
  <div class="form-check">
      <label for="is_deadline_true" class="form-check-label">設定する</label>
      <input type="radio" id="is_deadline_true" name="app[is_deadline]" value="1"
             v-model="app.is_deadline"
             v-on:change="checkDeadline"
      >
      <label for="is_deadline_false" class="form-check-label">設定しない</label>
      <input id="is_deadline_false" type="radio" name="app[is_deadline]" value="0"
             v-model="app.is_deadline"
             v-on:change="checkDeadline"
      >
  </div>
</div>
<div class="form-group" v-show="deadline_show">
  <label for="deadline_at">投票締切日時</label>
  <input id="deadline_at" type="date" name="app[deadline_at]" 
        class="form-control"
         v-model="app.deadline_at"
         data-vv-as="投票締切日時"
         v-validate ="'date_format:YYYY-MM-DD'"
  />
</div>
```
今回は、投票締切というラジオボタンで、設定するを選択されている時のみ、
投票締切日時を必須にするという処理を行います。
htmlは先ほどと特に変化はないのですが、radioボタンの値が切り替わった時に動く
checkDeadlineというメソッドを作りました。

```javascript:app.vue
checkDeadline: function () {
// 締切日時を設定していない場合、締切日時の値を空にする
    if(this.app.is_deadline == 0) {
        // 任意項目にする
        this.$validator.detach('app[deadline_at]');
    } else {
        // 必須項目にする
        this.$validator.attach({
            name: 'app[deadline_at]',
            alias: '投票締切日時',
            rules: 'required',
            scope: this.app.deadline_at
        });
    }
}
```
`attach`を使えば、ある条件下の時に、バリデートの条件を追加することができます。
バリデート条件を外したい時は、`detatch`を使用します。
ちなみに、最初`scope`を指定しなかったために、app[deadline_at]の値が入力されていても、
バリデートに引っかかるという沼にハマりました。`scope`で、ちゃんとどの値を参照しないといけないのか指定してあげる必要がありそうです。

### フォームの送信ボタンを押したら、バリデートが走る
フォームの送信ボタンを押した時に、バリデートが走らないとそもそも意味ないですね。
なので、送信ボタンを押下した時に、バリデートが走るメソッドを準備します

```html:app.vue
<button type="button" class="btn btn-primary" v-on:click="postApp">
作成する
</button>
```

```javascript:app.vue
postApp: function () {
  // バリデートの判定
  this.$validator.validateAll().then((result) => {
      if (result) {
         //エラーがなかった時の処理を下に記述
      }
  });
},
```

上記のメソッドだけで、エラーがあったら、エラーメッセージが自動で表示されるようになります。

![Mar-21-2018 10-51-49.gif](https://qiita-image-store.s3.amazonaws.com/0/148823/30a47d7a-20ce-7316-8298-c579da7f06e0.gif)


### 終わり
こんな感じで、簡単にバリデート処理を書けます。
少ない記述で書けるので、vue.jsを使う時はVeeValidateを使うと
かなり捗るのではないでしょうか？

参照
[VeeValidateドキュメント](http://vee-validate.logaretm.com/)
[VeeValidateを使ってみる](https://pinzolo.github.io/2017/10/25/vee-validate-regex-and-ja-locale.html)