Buefy と VeeValidate でお手軽フォームバリデーション！

#概要
BuefyとVeeValidateを組み合わせると、レスポンシブ && バリデーション付きのフォームが爆速で作れるよっていう話です。

#Buefyとは

![buefy.1d65c18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/b86064cb-e996-299e-90c2-157a5e7eecca.png)

[Buefy](https://buefy.org/) は Vue.js と Bulma をベースとした、UIコンポーネントライブラリです。


レスポンシブに対応した[ボタン](https://buefy.org/documentation/button)や [Date picker](https://buefy.org/documentation/datepicker) など、便利なコンポーネントが多数用意されています。

【Buefyのいいところ】

- 軽量

- 配色やレイアウトに Bulma の知識がそのまま使える

- SCSSの変数を上書きすることでサイトのテーマカラーなどを[カスタマイズ]( https://buefy.org/documentation/customization )可能

#VeeValidateとは

![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/fe26f7b7-4a43-edd8-4939-b1978145aab6.png)

Vue.js をベースとしたフォームバリデーション・フレームワークです。

様々なルールによるバリデーションがこれ一本で簡単にできます。

【VeeValidateのいいところ】

- [ルール](https://baianat.github.io/vee-validate/guide/rules.html)が豊富に用意されている

- 自分で[カスタムルール](https://baianat.github.io/vee-validate/guide/custom-rules.html)を作ることもできる

- バリデーションだけではなくエラーメッセージの表示やエラー時の挙動なども色々制御できる

#なぜ Buefy + VeeValidate か

これら2つが補完しあう形で、バリデーションのめんどくささが一挙に解消されるからです。

【普通に作ろうとするとめんどくさい所一覧】

|めんどくさい所 |どう解決されるか|
|---|---|
|チェック用の関数を色々作らなきゃいけない |VeeValidate に一通り用意されてる |
|チェックをリアルタイムにやらなきゃいけない |VeeValidate が普通にやってくれる |
|エラーメッセージ表示部分を作らなきゃいけない |Buefy の field コンポーネントにメッセージ表示用の属性が用意されているので、別個に作成しなくてOK|
|エラー時にフォームの見た目を変更したい |Buefy の field コンポーネントには色やアイコンを設定するための属性が用意されている|
|エラー時は値が送信できないようにしたい |エラー判定用の関数がVeeValidateに用意されている|

具体的にどう実装するかは以下で説明していきます。

#インストール

どちらも基本 npm か yarn でインストールして`Vue.use()`で登録するだけです。

[Buefyのインストール](https://buefy.org/documentation/start)

[VeeValidateのインストール](https://baianat.github.io/vee-validate/guide/getting-started.html#installation)

ただしVeeValidateはデフォルトが英語なので、日本語のメッセージを表示させたい場合はローカライズする必要があります。
ローカライズの方法については[こちら。](https://baianat.github.io/vee-validate/guide/localization.html#localized-files)

以下はVue CLI を利用した場合の例です。

```javascript:main.js

import Vue from 'vue'

/* Buefy */
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'

/* VeeValidate */
import VeeValidate, { Validator } from'vee-validate'
import ja from 'vee-validate/dist/locale/ja' // ローカライズ用パッケージ

Vue.use(Buefy)
Vue.use(VeeValidate);
Validator.localize('ja', ja); // ローカライズする

// 以下略
```




#VeeValidateの使い方
本題の実装に入る前に、それぞれのライブラリのおさらいを簡単にします。

まずはVeeValidateから。

```HTML:VeeValidate
メールアドレス:
<input type="text" v-validate="'required|email'" name="email" >
<div>{{ errors.first('email') }}</div>
```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/aa174e35-b95d-2cb6-16b8-6464a84b9baf.png)

- `v-validate`属性にチェックしたい内容を「｜」区切りで入れます。
例えば上では'required'と'email'を指定しているため、入力が空だったりアドレスの形式がおかしかったりするとエラーになります。

- エラー情報は全て`errors`に格納され、`.first('fieldName')`でエラーメッセージを一つ取り出すことができます。

#Buefyのフォームの書き方

Buefyにはフォーム用のコンポーネント`<b-field>`が用意されています。

```HTML:Buefy
<b-field
    label="メールアドレス"
    type="is-danger"
    message="これはメッセージです"
>
    <b-input type="text"></b-input>
</b-field>
```

![hshsrfhr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/b2cecd0d-bf08-45a7-7590-298ab177df86.png)


- label 属性に入れた文字列がそのフォームのラベルとして表示されます。

- type 属性には、'is-danger', 'is-white'などフォーム色を指定する文字列を入れます。
Bulmaをやってた人なら[どういう色](https://bulma.io/documentation/overview/colors/)があるかすぐに把握できると思います。
また、これらの色は好きに[カスタマイズ](https://buefy.org/documentation/customization)することが可能です。


#フォームの実装

さてようやく本題のフォームの実装です。

前2節で見てきたように、

① `<b-field>`の message 属性にエラーメッセージをバインドし、
② エラーがあるときのみ type 属性に'is-danger'が入るようにする

ことで、良い感じのフォームができあがります。

```HTML
<b-field 
    label="メールアドレス"
    :type="{'is-danger': errors.has('email')}"
    :message="errors.first('email')"
    horizontal
>
    <b-input 
        type="text"
        name="email" 
        v-model="email"
        v-validate="'required|email'" 
        data-vv-as="メールアドレス"                
    ></b-input>
</b-field>
```

![haddb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/592c47b9-63e6-14be-cc3d-b228ad436bc8.png)

- `errors.has('email')`はエラーがあるかどうかをBooleanで返すので、[Vue.jsのクラスのバインディング](https://jp.vuejs.org/v2/guide/class-and-style.html#HTML-%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E3%83%90%E3%82%A4%E3%83%B3%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0)の記法を使って、

```html
:type="{'is-danger': errors.has('email')}"
```

のように書くことができます。

- `data-vv-as`にはエラーメッセージで表示させたいフィールド名を指定します。これがない場合は以下のように name がそのまま表示されます。

![ggggggggg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/3602545e-5e2f-5850-accc-0b574746fe3d.png)


- `horizontal`属性を付与すると、ラベルとフォームが横並びになります。

#エラー発生時の制御

バリデーションをしてもそのまま送信できてしまってはあまり意味がありません。
そのためデータを送信するメソッド内でもバリデーションを行い、処理を制御する必要があります。


そのためにはVeeValidateの`$validator.validate()`を用います。

```javascript
methods: {
    /**
     * メールアドレスを送信するメソッド
     */
    async registerEmail() {
        const isValid = await this.$validator.validate()
        if(!isValid) return;

        // 以下、送信する処理
    }
}
```

`$validator.validate()`はバリデーションを行った後、エラーがなかったかどうかを`Promise`で返却します。

返り値が`Promise`なので async, await を忘れずにつけましょう。

（先述の`errors.has()`もエラーがあるかどうかを返しますが、バリデーションまでは行わないのでここでは不適です）

#終わりに
以上でレスポンシブデザイン＆バリデーション付きのフォームが少ない記述量で作成できました。

エラーを表示する部分をゴチャゴチャ作らなくていいのが個人的には一番嬉しいポイントです。