フロント側のバリデーション
自社でフォームの UIを担当することがあります。
フロント側からフォームのバリデーションを作るのですが、
今回学びが多かったので忘備録として書き留めていきます。
その際に利用したjQueryはこちらにまとめました。
https://okinawanpizza.hatenablog.com/entry/2021/05/01/234915
バリデーション
入力内容が適当かどうかをチェックすこと。
正規表現
さまざまな文字列を一つの文字列で表すことができる記法のことを指す。
javascriptだと/ac+c/
などのようなスラッシュで囲まれた正規表現リテラルを利用する。
https://okinawanpizza.hatenablog.com/entry/2020/05/22/104507
電話番号、メールアドレス
電話番号もメールアドレスも正規表現でのチェックがメインとなります。
メールアドレスや電話番号のルールに合わせて正規表現を作り、
当てはまるかチェックすることでバリデーションを作成します。
1 2 3 4 5 |
//メールアドレスのバリデーション(例) var regexp = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/; if (!regexp.test(content)) { flag = false; } |
● A.test(B)
test()メソッドは、正規表現と指定された文字列が一致するかどうかを調べるメソッドです。論理値を返してくれます。
1 2 3 4 5 6 |
//電話番号のバリデーション(例) let contentTel = content.replace(/\D/g, ''); console.log(contentTel); if !contentTel.match(/^(0[5-9]0[0-9]{8}|0[1-9][1-9][0-9]{7})$/)) { flag = true; } |
● A.replace(B,C)
replace()メソッドは文字列の中にある、指定した文字列を別の文字列へと置換してくれます。
つまりAという文中にあるBをCに変更してくれます。
この場合は数字以外をトリミングするといった意味合いに近いです。
指定した入力項目だけを必須項目にする
入力フォームって全てが必須項目ではないことが多いと思います。
フォームを作るたびに入力チェックのコードを書くのは面倒なので、
inputに何かしらのマークをつけて、そのマークがついたものに対してイベントが発火するようにしていきます。
手順は以下の通り。
①バリデーションを記憶するためのハッシュを作る
②requireという名前のクラスがついたinput全てに背番号をつけてハッシュに格納する
③入力が終了した瞬間に入力チェックを行い、結果をハッシュに登録する
④入力項目のタイプに応じた、バリデーションを作成する。
⑤ハッシュの値全てがtrueなら、ボタンを押せる状態にする
まずは①、②
1 2 3 4 5 6 7 |
let valitationHash = {}; let $must = $(".require"); $must.each(function (index, element) { let name = "input" + index; $(element).attr("data-input-name", name); //⑥番のおまけで少し変更あり valitationHash[name] = false; }) |
クラスがついた要素を全て取得するのはjQueryだとすごく楽でした。
取得した要素をループさせてそれぞれの要素にdata-input-name属性を追加します。
こちらの値が背番号になり、入力チェックのタイミングで使用します。
ハッシュの中はvalitationHash = {input1: false, input2: false, ....}
となります。
次に③
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
$(".must").change(function() { checkValitate(this); }) function checkValitate(elem) { let type = $(elem).attr("type"); let name = $(elem).attr("data-input-name"); let flag = true; let content = $(elem).val(); if(type == 'text') { //type="text"の場合の入力チェック if(content == ""){ flag = false; } } else if (type == 'email') { //type="email"の場合の入力チェック var regexp = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/; if (!regexp.test(content)) { flag = false; } } else if (type == 'tel') { let contentTel = content.replace(/[━.*‐.*―.*-.*\-.*ー.*\-]/gi,''); console.log(contentTel); if (!contentTel.match(/^(0[5-9]0[0-9]{8}|0[1-9][1-9][0-9]{7})$/)) { flag = false; } else if (type == 'example'){ if(checkExample()){ flag = false; } } setValitationHash(name , flag) //⑤で作る関数に背番号と結果をハッシュに格納 } |
inputのタイプ別にバリデーションの項目が違うので
type別に分岐させます。
⑤ハッシュの値全てがtrueなら、ボタンを押せる状態にする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function setValitationHash (name, boolean){ valitationHash[name] = boolean; pushable(valitationHash); } function pushable (hash) { let pushableValue = true; for (let key in hash) { if(hash[key] == false){ pushableValue = false; } } if(pushableValue){ buttonOn() } else { buttonOff() } } function buttonOn() { $(".button").prop("disabled", false); } function buttonOff() { $(".button").prop("disabled", true); } |
ハッシュの値をループで取り出して、全てtrueであれば送信ボタンを押せるようにする処理です。
ハッシュをループさせる方法がわからず、
いろんな記事を参考にした結果以下の方法が見つかりました。
(ハッシュはインデックスを持たないため、通常の配列のループ方法とは違うらしいです)
1 2 3 4 |
let ageList = {yusaku:"12", kiyomi: "25", yuki: "30"}; for (let name in ageList) { console.log("私は" + name + "、" + ageList[name] + "です。") } |
おまけ:いろんなチェックを追加したい、、
次に出てきた壁がこちら
そう、選択式のチェック項目です(笑)
どうにかrequire仲間に加えてあげたい、、
⑥selectタグを認識できるように修正
汎用性を持たせるために、
inputの属性に新しく data-input-typeを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$must.each(function (index, element) { let name = "input" + index; setTypeAndName(element, name) valitationHash[name] = false; }) function setTypeAndName(element, name) { let type = "text"; let tagname = $(element).prop("tagName"); if(tagname == "SELECT"){ type = "select"; } else if (tagname == "INPUT"){ type = $(element).attr("type"); } else if (tagname == "SPAN") { type = "checkbox" } $(element).attr("data-input-name", name); $(element).attr("data-input-type", type); } |
data-input-typeの値に select を追加し、
select用のチェックを追加できるようにします。
prop("tagName")でタグの値を取得できます。
そしてcheckValitate(elem)関数に処理を追加
1 2 3 4 5 6 7 8 9 10 |
function checkValitate(elem) { let type = $(elem).attr("data-input-type"); // typeじゃなくて data-input-type属性を取得 . . } else if (type == 'select') { //data-input-typeがselectの時 //処理内容 } . . } |
こうやって、typeの種類とチェック内容を増やしていきます。
おわり
多分なみのエンジニアであれば数時間で組めるんだろうけど、
自分は12時間くらいかかってすごく死闘を繰り広げました。
今回のコーディングでバリデーションの他のライブラリを調べるきっかけにもなってすごくいい経験になりました!!
あと、ワードプレスのコンタクトフォーム7など
フロントでのバリデーション設定がないものでも意外に使えたりしたので、よかったかなと思います(笑)
他にも「チェックボックスに一つ以上チェックついていたら」「内容が全てカタカナだったら」「ラジオボタンが...」
などいろんな状態を想定して書いてみたいです。
もっといい方法があれば沢山アドバイスいただけると嬉しいです!!
ご清澄ありがとうございました!!
参考
test()メソッド
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
正規表現
https://qiita.com/soarflat/items/2b50c1efe2ea54a762d7
連想配列をループさせる
https://qiita.com/wifeofvillon/items/15359535a834832e08ea