【HTML/CSS】リアルタイムな正規表現検証を簡単にフォームに実装する方法【Rails】

# 初めに
https://qiita.com/ynkn0829/items/d329e092daba523667dd

　この記事は、上記記事で紹介したポートフォリオで使用した技術を切り出した記事になります。もし宜しかったらこちらもご覧ください。
 また、この記事はGIF画像を挿入しておりますが、あまり滑らかに動かない可能性があります。GIF画像をクリックして頂けるとGyazoのURLへ移動することが出来ますので、そちらでしたらヌルヌル動くかと思います。

# イメージ図
[![Image from Gyazo](https://i.gyazo.com/0769d392bbd6d5ba26491f6394feccff.gif)](https://gyazo.com/0769d392bbd6d5ba26491f6394feccff)

　今回紹介する方法を使用すると、上記GIF画像のinput要素のように、

- フォーカスされたら要素が大きくなる・背景が白っぽくなる
- 正規表現にマッチするなら枠が緑色に、マッチしないなら赤色になる
- 正規表現とマッチしない状態で送信ボタンを押すと、入力内容が送信される前に入力アシスタントを表示する  

といった機能を割と簡単に実装出来るようになります。

## HTMLで正規表現を記述する  

```ruby:/views/devise/registrations/new.html.erb

<div class="field font sign-up">
  <%= f.label :nickname %><br />
  <%= f.text_field :nickname, autofocus: true, autocomplete: "off", required: true, maxlength: 8, pattern: "^([a-zA-Z0-9]{1,8})$", placeholder: "^([a-zA-Z0-9]{1,8})$" %>
</div>
```

　上記コードはGIF画像でいうところの「Nickname」部分のフォームのソースコードです。form_withを使ったinput要素ですが、`f.text_field :nickname`の後に何やらゴチャゴチャ書かれていますね。今回特に注目して頂きたいのは下記の部分です。

- required: true
  - 必須項目になる
- maxlength: 8
  - 8文字までしか入力出来なくなる
- pattern: "^([a-zA-Z0-9]{1,8})$"
  - この正規表現(半角英数1~8文字)にマッチする入力内容しか通さなくなる  

　そして、これらの条件を満たさないまま送信をしようとすると、
[![Image from Gyazo](https://i.gyazo.com/bc77e2c4bb9270ddc923251695e9ab4b.jpg)](https://gyazo.com/bc77e2c4bb9270ddc923251695e9ab4b)
以下のような入力アシスタントが表示される具合です。

## 裏でどのような処理がされているか  
　詳しい内容は下記URLに全て書かれています。

https://developer.mozilla.org/ja/docs/Learn/Forms/Form_validation

　ここでは、今回の内容に関係する部分のみ引用します。

> 要素が妥当な場合は、次のようになります。

> - 要素が CSS の :valid 疑似クラスに一致します。これにより、妥当な要素に特定のスタイルを適用することができます。
> - ユーザーがデータを送信しようとすると、ブラウザーは止めるものが他になければ（JavaScript など）、フォームを送信します。

> 要素が不正なときは、次のようになります。  

> - 要素が CSS の :invalid 疑似クラスに一致します。これにより、不正な要素に特定のスタイルを適用することができます。
> - ユーザーがデータを送信しようとすると、ブラウザーはフォームをブロックしてエラーメッセージを表示します。

　つまり、HTMLがフォームの入力内容を常に監視し、その検証結果を要素の擬似クラスとして出力するということです。
　擬似クラスがどのようなものかと言うと、簡単に言えば「そのクラスの状態」のことを指します。例えば`<div class="test"></div>`のような要素があるとして、この要素をCSSで装飾する時は

```CSS:style.css
.test {
  display: flex;
}
```
のような記述になるかと思います。この要素がホバーされると裏では擬似クラス`:hover`が要素に付与されるので、

```CSS:style.css
.test:hover {
  background-color: red;
}
```
のような記述がCSSにあると、これが適用されるようになります。これを利用すれば、

```CSS:style.css
.test {
~~省略~~
  background-color: blue;
  transition: all 0.3s ease;
}

.test:hover {
  background-color: red;
  transform: scale(1.1, 1.1);
}
```

のように記述をすると、testクラスを持った要素は、「ホバーされると0.3秒掛けて色が青から赤へ、大きさが縦横ともに1.1倍になる」といった装飾を適用することが出来る、という寸法です。ちなみに、`transition`は要素の変化を滑らかに繋ぐためのプロパティで、`transform`は要素の形状を変化させるためのプロパティです。
　たったこれだけの記述を追加するだけでアプリに動きを出せる訳ですから、労力対効果は高そうですね。

## 擬似クラス別にCSSを記述してみる
　それでは、入力内容の検証が行われるフォームに装飾を追加してしてみましょう。

```CSS:style.css
.input {
~~省略~~
  transition: all 0.3s ease;
}
```

　まずはいつも通りにinputクラスにCSSを記述し、フォームを作成します。そして`transition`を追加することで、これから記述していく変化の内容が滑らかなアニメーションで表現されるようにしておきます。
　次に、要素が`focus`された時に起こしたい変化を記述していきます。

```CSS:style.css
.input {
~~省略~~
  transition: all 0.3s ease;
}

.input:focus {
  transform: scale(1.1, 1.1);
  background-color: rgba(223, 223, 223, 0.5);
}
```
　更に今回は入力内容の検証も行いたいので、条件を満たさない時は枠を赤色に、条件を満たしたら緑色に変化するようにします。条件を満たさない時は擬似クラス`:invalid`が、満たすときは`:valid`が適用されますので、

```CSS:style.css
.input {
~~省略~~
  transition: all 0.3s ease;
}

.input:focus {
  transform: scale(1.1, 1.1);
  background-color: rgba(223, 223, 223, 0.5);
}

.input:focus:invalid {
  border: red 5px solid;
}

.input:valid {
  border: rgb(2, 175, 2) 6px solid;
  background-color: rgba(223, 223, 223, 0.5);
}
```
これで「フォーカスされている・入力内容が条件を満たさない」場合は枠が赤色に、「入力内容が条件を満たす」場合は緑色に変化させることが出来ます。

## まとめ
　上記の記述だけでは、「入力したNicknameが既に使われているかどうか」といった「データベースと照合する検証」は行うことが出来ません。HTMLで行うことが出来るのは、あくまで入力の書式に関する検証のみになります。リアルタイムでデータベースとの照合を行う方法は発見することが出来ませんでした。
　その方法を発見し次第また記事にしようと思います。