VeeValidateを使ってVue.jsで会員登録のバリデーションをしてみた

Vue.jsで会員登録型のサイトを作っているのですが、VeeValidateを使うとフロントサイドで簡単にバリデーションを行うことができたので紹介していきます。

VeeValidate
https://github.com/logaretm/vee-validate

## 環境情報
- vue: 2.6.10
- vee-validate: 2.2.10

## 完成イメージ
![スクリーンショット 2019-06-18 1.05.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436133/c7e47f70-2b65-7870-34b5-c3d1d600f056.png)

## 事前準備
VeeValidateのインストール

```
npm install vee-validate --save
```

VeeValidateをVueで呼び出す

```js:Signup.vue
import Vue from 'vue';
import VeeValidate from 'vee-validate';

Vue.use(VeeValidate);
```

## 使い方
基本の型は以下のようになります。


```vue:Signup.vue
<form>
  <div class="form-group">
    <input
      type="email"
      placeholder="email"
      class="form-control"
      v-model="email"
      name="email"
      v-validate="'required|email'"
      data-vv-as="メールアドレス"
     >
    <div class="form-control-feedback" v-show="errors.has('email')">
      <p class="alert alert-danger">{{ errors.first('email') }}</p>
    </div>
  </div>

  <div class="form-group">
    <button type="button" class="btn btn-primary" v-on:click="submit">登録</button>
  </div>
</form>
```

v-validateの中にバリデートのルールを書き込みます。
複数選択するときは`|`で区切ります。

```vue
<input v-validate="'required|email'" name="field" type="text">
```

### バリデートルール

|ルール  |機能  |
|---|---|
|required  |入力必須  |
|email  |メールアドレス形式 |
|numeric  |半角数値のみ |
|min |最小入力文字数 |
|max  |最大入力文字数 |


### エラーメッセージ


以下はエラーメッセージの表示部分です。
inputフォームのname属性を使います。

```vue
<div class="form-control-feedback" v-show="errors.has('email')">
  <p class="alert alert-danger">{{ errors.first('email') }}</p>
</div>
```

### エラーメッセージの日本語化

デフォルトでエラーメッセージの内容は英語になっていますので、日本語になおす必要があります。

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

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


data-vv-as=""の中に書いた日本語が表示されるようになります。

```vue:Signup.vue
<div class="form-group">
  <input
    type="email"
    placeholder="email"
    class="form-control"
    v-model="email"
    name="email"
    v-validate="'required|email'"
    data-vv-as="メールアドレス"
   >
  <div class="form-control-feedback" v-show="errors.has('email')">
    <p class="alert alert-danger">{{ errors.first('email') }}</p>
  </div>
</div>
```

![スクリーンショット 2019-06-18 1.40.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436133/c6a431c6-8166-accf-54b2-a5cfb17a81dc.png)


## ボタンを押したらバリデート

ボタンを実装します。
button type="submit"にするとバリデートがうまく走らないので注意です。

```js:Signup.js
<button type="button" class="btn btn-primary" v-on:click="submit">登録</button>
```

バリデートがないときの処理を以下のように記述していきます。

```js:Signup.vue
methods: {
  submit: function() {
    this.$validator.validateAll().then(async result => {
      try {
        if (result) {
          //バリデートがないときの処理 (成功したとき)
          const res = await axios.post("/signup", {
            name: this.name,
            email: this.email,
            password: this.password
          });
        }
      } catch (err) {
        console.log(err);
      }
    });
  }
}
```


## サンプルコード
template部分

```vue:Signup.vue
<form>
  <div class="form-group">
    <input
      type="text"
      placeholder="username"
      class="form-control"
      v-model="name"
      name="name"
      v-validate="'required|max:10'"
      data-vv-as="ユーザーネーム"
    >
    <div class="form-control-feedback" v-show="errors.has('name')">
      <p class="alert alert-danger">{{ errors.first('name') }}</p>
    </div>
  </div>
  <div class="form-group">
    <input
      type="email"
      placeholder="email"
      class="form-control"
      v-model="email"
      name="email"
      v-validate="'required|email'"
      　data-vv-as="メールアドレス"
    >
    <div class="form-control-feedback" v-show="errors.has('email')">
      <p class="alert alert-danger">{{ errors.first('email') }}</p>
    </div>
  </div>
  <div class="form-group">
    <input
      type="password"
      placeholder="password"
      class="form-control"
      v-model="password"
      name="password"
      v-validate="'required|min:4|max:20'"
      data-vv-as="パスワード"
    >
    <div class="form-control-feedback" v-show="errors.has('password')">
      <p class="alert alert-danger">{{ errors.first('password') }}</p>
    </div>
  </div>
  <div class="form-group">
    <button type="button" class="btn btn-primary" v-on:click="submit">登録</button>
  </div>
</form>
```

script部分

```js:Signup.js
<script>
import axios from "axios";

export default {
  data() {
    return {
      name: "",
      email: "",
      password: ""
    };
  },
  methods: {
    submit: function() {
      this.$validator.validateAll().then(async result => {
        try {
          if (result) {
            const res = await axios.post("/signup", {
              name: this.name,
              email: this.email,
              password: this.password
            });
          }
        } catch (err) {
          console.log(err);
        }
      });
    }
  }
};
</script>
```


## 完成イメージ(再掲)
bootstrapで少し見栄えを整えています。
みなさんもVeeValidateを使ってバリデーションをしてみてくださいね！便利です。

(追記)
サーバーサイドでのvalidationはexpress validatorにて行いました。
https://express-validator.github.io/docs/


![スクリーンショット 2019-06-18 1.05.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436133/c7e47f70-2b65-7870-34b5-c3d1d600f056.png)