【Vue.js】入力フォームにバリデーションをつける

Vue.jsを使ってバリデーション（正しく入力されているか検証する機能）のついた入力フォームを作成してみました。

よく入力フォームで「メールアドレスが正しく入力されていません」とかエラーメッセージが表示されるのを見たことがあるかと思いますが、それらをVue.jsの条件付きレンダリング、算出プロパティ、双方向バインディングを用いて実装していきます。

ユーザーが情報を送る前に入力のミスを動的に教えてあげることで、結果的にUXの優れたアプリに仕上げることが可能です。

## やること

今回は以下のような基本的なバリデーションチェックを名前、メール、電話番号それぞれに施していきます。

- 名前：〇文字以上か
- メール：正しい形式か
- 電話番号：~~または~~になっていた場合

バリデーションチェックは他にも色々なパターンや正規表現があったりしますので、どういう仕組みになってるかを理解した上で、実装できるようになりましょう。

## 【名前】 〇文字以上かチェック

「文字数の合計が4文字未満だった場合エラーメッセージを表示する」バリデーションを施していきます。

エラーメッセージにCSSで警告色を付けたりできるように ”error”というclassを付けてあげています。

### HTMLの実装

HTMLは以下のようにv-ifで文字数が違うことを知らせるエラーメッセージを設定しましょう。

```html
<div id="app">
  <div class="form-area__name">
    <p>名前</p>
    <input type="text" name="name" v-model="name"/>
    <p v-if="isInValidName"class="error">名前は4文字以上で入力してください</p>
  </di
</div>
```

### Vue.jsの実装

文字列が4文字以上かチェックする処理を施します。

```jsx
new Vue({
  el: '#app',
  data(){
    return {
      name: 'name',
    };
  },
  computed:{
    isInValidName(){
			//文字列が4文字以上かチェックする
      return this.name.length < 4;
    }
  }
});
```

## 【メール】正しい形式かチェック

メールアドレスが「~~@~~.~~」といった形式になっているか判定するバリデーションを施します。

### HTMLの実装

```html
<div id="app">
  <div class="form-area__email">
    <p>メールアドレス</p>
    <input type="text" name="email" v-model="email">
    <p v-if="isInValidEmail" class="error">メールアドレスの形式で入力してください。</p>
  </div>
</div>
```

### Vue.jsの実装

入力内容が正規表現担っているかを判定する処理を施していきます。

メールアドレスの正規表現は他にも色々ありますので、使い方さえ理解したらググってそのサービスに適した物を使うようにしましょう。

```jsx
new Vue({
  el: '#app',
  data(){
    return {
      email: 'email@email.com'
    };
  },
  computed:{
    isInValidEmail(){
			//メールアドレスとして判定される文字列と記号の組み合わせを定数化
      const reg = new RegExp(/^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/);
			//指定した組み合わせになっていなかった場合判定を返す。
      return !reg.test(this.email);
    }
  }
});
```

## 【電話番号】〇文字かつ、数値になっているかチェック

「~~または~~になっていた場合」と、複数の条件式を与えてバリデーションチェックを施します。

### HTMLの実装

```html
<div id="app">
  <div class="form-area__tel">
    <p>電話番号</p>
    <input type="tel" name="tel" v-model="tel">
    <p v-if="isInValidTel" class="error">電話番号は8桁で入力してください。</p>
  </div>
</div>
```

### Vue.jsの実装

こちらでは、「入力された文字列が8文字未満、または"数値でない"場合に」エラーメッセージを返してあげる処理を書きます。

```jsx
new Vue({
  el: '#app',
  data(){
    return {
      tel:'12345678'
    };
  },
  computed:{
    isInValidTel(){
      const tel = this.tel;
			// 入力された文字列が8文字未満、または"数値でない"ばあいに返す
      const isErr = tel.length < 8 || isNaN(Number(tel));
      return isErr;
    }
  }
});
```

## 【補足】v-modelを使わない擬似的双方向バインディングの実装

入力したタイミングでJavaScript側に即座にデータ反映させることは上記のようなv-modelを使わなくても実装が出来ます。

- 入力データを加工したい時
- 入力データを使ってリアルタイムで他の処理をさせたい

### サンプルコード

入力された文字をリアルタイムで表示させるといったプログラムのサンプルです。

### HTMLの実装

```html
<div id="app">
  <input type="text" @input="setText" :value="text">
  <p>入力された文字は：{{text}}</p>
</div>
```

### JavaScriptの実装

フォームに入力された内容をそのまま返してあげる処理を記述します。

```jsx
new Vue({
  el: '#app',
  data(){
    return {
      text:"aaaaaa"
    };
  },
    methods: {
      setText(e) {
        this.text = e.target.value;
      }
    }
});
```

このような処理はv-modelでの実装が難しいです。

なぜなら、v-modelは「データとテンプレート側の記述を、一対一で双方向バインディングするもの」で、それ以外の処理をするのが難しいからです。

v-modelで対応ができないような処理がでてきた時は、イベントハンドリングを使った実装をしてみましょう。

## まとめ

今回のはかなり基本的なバリデーションチェックになりますが、これらの操作はJavaScriptでかなり頻出する操作になると思います。

うまく組み合わせることで、電卓を作ったりピアノ作ったり動的なアプリを作ることができそうです。

おつかれさまでした！

## 参考記事

- [たった1日で基本が身に付く！　Vue.js　超入門](https://www.amazon.co.jp/%E3%81%9F%E3%81%A3%E3%81%9F1%E6%97%A5%E3%81%A7%E5%9F%BA%E6%9C%AC%E3%81%8C%E8%BA%AB%E3%81%AB%E4%BB%98%E3%81%8F%EF%BC%81-Vue-js-%E8%B6%85%E5%85%A5%E9%96%80-%E7%9F%B3%E4%BA%80-%E5%BA%83%E5%A4%A7-ebook/dp/B089LDYFV1)