【Rails6】新・JavaScriptによる「入力フォームの内容のリアルタイムチェック機能」の実装例

※2022年から技術系の記事は[個人ブログ](https://yamaday0u.net/category/programmer/)に投稿しております。ぜひこちらもご覧ください→[yamaday0u Blog](https://yamaday0u.net/category/programmer/)

以前、[【Rails6】JavaScriptによる「入力フォームの内容のリアルタイムチェック機能」の実装例](https://qiita.com/yamaday0u/items/21fbc89aa22527a9a875)という記事で、入力フォームのリアルタイムチェック機能の実装方法を紹介しましたが、この実装方法には以下の問題がありました。

- エラーメッセージのタグを`hidden`で隠しているので、フォームの中に不自然な空白がある
- 複数のタイプのエラーメッセージを表示しようとすると空白がさらに大きくなってしまう

今回はこれを改善し、しかもパワーアップしました。
前回と同様にjQueryのようなライブラリは使用せず、そのままのJavaScriptで実装したことが今回もポイントです。

## 実行環境
Rails 6.0.3.6

## 動作確認
今回のリアルタイムチェック機能の仕様は以下の通りです。

- 入力された値によって以下のエラーメッセージが表示される
    - 半角数字以外の場合→「価格は半角数字で入力してください」
    - 300〜9,999,999の範囲外の場合→「価格は300〜9,999,999の範囲で設定してください」
- 正しい値を入力するとメッセージが非表示になる

[![Image from Gyazo](https://i.gyazo.com/95b6aee350525bdd0aed44cb17370e23.gif)](https://gyazo.com/95b6aee350525bdd0aed44cb17370e23)

## Javascriptのコード
メインとなるJavaScriptのコードは以下の通りです。

```app/javascript/validation.js
//validationイベントを定義
const validation = () => {
  //エラーメッセージを表示するための要素を取得して変数化
  const priceErrorElement = document.getElementById("price-error");
  //フォームの値が入る要素を取得して変数化
  const itemPrice = document.getElementById("item-price");

  //ここから半角数字での入力を促すイベント
  //半角数字でないものにマッチする正規表現を変数化
  const pricePattern = /^\d+$/;

  //入力フォームでキーが離されたときにイベントが発生
  itemPrice.addEventListener("keyup", e => {
    //idがprice-character-errorの要素（エラーメッセージ）を取得して変数化
    const errorMessageCharacter = document.getElementById("price-character-error");
    //入力された値が正規表現にマッチしている or 空白のとき
    if (pricePattern.test(itemPrice.value) || itemPrice.value == "") {
      //エラーメッセージが存在しているとき
      if (errorMessageCharacter != null) {
        //エラーメッセージを削除
        errorMessageCharacter.remove();
      }
    //入力された値が正規表現にマッチしていないとき
    } else   {
      //エラーメッセージが存在していないとき
      if (errorMessageCharacter === null) {
        //エラーメッセージを挿入
        priceErrorElement.insertAdjacentHTML('afterend', '<div id="price-character-error" class="price-error">価格は半角数字で入力してください</div>' );
      }
    }
  });
  //ここまで半角数字での入力を促すイベント

  //ここから300〜9,999,999の範囲での入力を促すイベント
  //最小値と最大値を変数化
  const minimumPrice = 300;
  const maximumPrice = 9999999;

  //入力フォームでキーが離されたときにイベントが発生
  itemPrice.addEventListener("keyup", e => {
    //idがprice-range-errorの要素（エラーメッセージ）を取得して変数化
    const rangeErrorMessage = document.getElementById("price-range-error");
    //入力された値が300より小さい or 9,999,999より大きいとき
    if (itemPrice.value < minimumPrice || itemPrice.value > maximumPrice ) {
      //エラーメッセージが存在していないとき
      if (rangeErrorMessage === null) {
        //エラーメッセージを挿入
        priceErrorElement.insertAdjacentHTML('afterend', '<div id="price-range-error" class="price-error">価格は300〜9,999,999の範囲で設定してください</div>' );
      }
    //入力された値が300以上 or 9,999,999以下のとき
    } else {
      //エラーメッセージの要素が存在しているとき
      if (rangeErrorMessage != null) {
        //エラーメッセージを削除
        rangeErrorMessage.remove();
      }
    }
  });
  //ここまで300〜9,999,999の範囲での入力を促すイベント
}

//ページが読み込まれた（load）ときに、validationイベントを実行
window.addEventListener("load", validation)
```

上記`validation.js`を`application.js`で読み込むことを忘れないようにしましょう。

```app/javascript/packs/application.js
require("../validation")
```

## Viewのコード
エラーメッセージを入れたい箇所に以下の要素を記述します。

```new.html.erb
<div id="price-error"></div>
```