phi

I'm a Game Programmer and Frontend Engineer passionate about programming education. Math / C / C++ / C# / JavaScript / HTML5 / CSS3 / Python

phiaryjust a creator

サーバーだけに頼る時代は終わった!? クライアントサイドでしっかり Validation する方法

9 years ago

未だに form の validation って, とりあえずなんでも受け付けてサーバー側で してエラー返ってきたらヘッダーなりダイアログなりでエラーメッセージを表示するなんてのをよく見ます.

某大手サイトなんかはエラーがあるとリロードしちゃったりするし...
ユーザーさんからすると入力した段階で何かしら間違いがあったらすぐに教えて欲しいですよね.

実はこの辺って HTML5 からクライアントサイドでもある程度チェックできるように整備されています. なのでライブラリを使わなくてもある程度サーバーに送る前に validation することができます.

今回は, その辺の機能をサンプルを交えつつ紹介していきたいと思います. 一通りやるべきことはリストアップしたつもりなのでよかったら参考にして下さい.

※このエントリーは, サーバーでは validation しなくていいよということではなくクライアントサイドでもある程度標準のやつで手軽にチェックできるからやっとくとUX向上するしサーバーへの負荷も減るよというお話です.

Demo

まずデモです. プロフィール以外は入力必須で, 未入力もしくは間違った入力の状態で submit ボタンを押すと色々と警告が出るのがわかるかと思います.

required 属性で入力必須にしよう

input 要素に required 属性を追加すると入力必須になります.

<input type='text' required />  

これで, 未入力時に submit ボタンを押すと下図のように警告が表示されるようになります.

ss

適切な type 属性を指定して validation しよう

type である程度 validation できます.

今回のサンプルでいうと emali の箇所で type='email' を指定しているので ちゃんと email の書式になっていないと警告がでます.

<input type='email' />  

ss

他にも telurl といった値を指定することができます.

pattern 属性に正規表現を指定して validation しよう

type だけではカバーしきれないことも多々あると思います.
そんなときには pattern 属性を使います.

ここに正規表現を指定することで様々なパターンチェックを行うことが出来ます.

今回は, パスワード部分で 数字, 小文字, 大文字それぞれを含む8文字以上の文字列という条件でチェックしています.

<input type='password' pattern='(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}' required />  

pass

下の方によく指定するパターンをまとめ載せているのでよかったら参考にしてください.

validation error 時の CSS を指定しよう

validation error になるとその要素に対して :invalid が有効になります.
なので element:invalid { ... } という形でスタイルを指定しておけば, validation に失敗したときに スタイルを変更することができます.

今回は下記のように validation が失敗したらラインが赤くなるよう指定しています.

input:invalid {  
  border-bottom-color: red;
  color: red;
  &:focus {
    box-shadow: 0 1px 0 0 red;
  }
}

invalid style

一度フォーカスした後に invalid style が適応されるようにしよう

普通に required を指定後に invalid style を指定してしまうと画面を開いた瞬間から 適応されてしまいユーザーを不快にさせてしまいます.

なので下記のように blur 時に .focused クラスを付与するようにして,

<input type='text' required onblur='this.classList.add("focused")' />  

CSS 側も .focused 時のみ invalid style が適応されるようにしましょう.

input.focused:invalid {  
  border-bottom-color: red;
  color: red;
  &:focus {
    box-shadow: 0 1px 0 0 red;
  }
}

これで最初に開いた時は普通に表示されて, blur 後に validation error になったら invalid style が適応されるようになります.

validation メッセージを変更しよう

input 要素の setCustomValidity(msg) 関数を使うことで簡単に変更することができます.
この関数に渡した文字列がそのまま警告文として使われます.

空文字を指定すると無効になります.

今回のデモでは input 要素の change イベントに関数を登録し,

<input type='text' onchange='check(this);' />  

javascript でチェックを行っています.

window.check = function(elm) {  
  if (/(ち◯ち◯|おっ◯い)/.test(elm.value)) {
    elm.setCustomValidity('卑猥な言葉が含まれています. 落ち着いて考えなおして下さい');
  }
  else {
    elm.setCustomValidity('');
  }
};

client validation message

追記: checkValidity() を使って全体をチェック & ボタンを無効化しよう

そもそも すべての Validation チェックが通らないと Submit を押せなくする っということもできます. って知ったかしてますが先ほど @habarhaba さんのコメント で知りましたw @habarhaba さんありがとうございます.

checkValidity() は, form, input, textarea などのメソッドで, 現在 validation をパスしているかどうかを bool 値で返してくれるメソッドです.

今回のデモでいうと, まずはじめに submit ボタンをデフォルトで無効化します.

<button name='btnSubmit' disabled>submit</button>  

そして form の input イベントに関数を登録します.

<form oninput='checkAll(this)'> ~ </form>  

これで form 内の要素に変更があるたびに checkAll() 関数が呼ばれるようになります.

あとは checkAll() 関数内で formcheckValidity() 関数を呼んで, 結果が false であれば validation エラーなので submit ボタンの disabled 属性に反転した値を代入します.

window.checkAll = function(form) {  
  form.btnSubmit.disabled = !form.checkValidity();
};

これですべての validation をパスしないと submit ボタンを押せないようになります.

Demo - クライアントサイドでしっかり Validation する(checkValidity)

ちょっと難点として, submit を押せない以上, 何の validation エラーで引っかかっているのかがわからなくなります. そのため, それぞれの要素で変更があるたびに validation エラーメッセージを表示する必要性がでてきます.

よく使う pattern 属性用の正規表現一覧

user 名とかに使えるやつ

  • 3文字以上 ... {3, }
  • 4文字以上8文字未満 ... {4,8}

パスワードとかに使えるやつ

  • 半角英数字 ... ^[a-zA-Z0-9]+$
  • 半角英数字で8文字以上 ... ^[a-zA-Z0-9]+$
  • 小文字, 大文字, 数字それぞれを含む 8 文字以上 ... (?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}

その他

  • 郵便番号 ... \d{3}-\d{4}
  • 電話番号 ... \d{2,4}-\d{3,4}-\d{3,4}

もっと色々なパターンを知りたいという方はこちらが参考になるかと思います.

HTML5におけるinput要素のpattern、type属性のおさらい - Qiita