つくる フォームの入力チェック
このレッスンで分かること
- 未入力の入力欄の
valueは空文字列で、そのまま falsy として判定できます- 検証に通らなかったときは、早期 return で先に進ませません
- エラーの表示と解除は、文字の書き換えと class の付け外しの両方で行います
つくる フォームの入力チェック とは
submit を止めたうえで入力内容を調べ、足りなければエラーを出して送信を中断する仕組みです。
ここまでで手に入れたもの
この章の 5 回で、イベント処理のひととおりがそろいました。addEventListener で処理を結び付け、event.target で発生元を知り、value で入力内容を読み、preventDefault() で既定の動きを止め、classList で見た目の状態を切り替える。今回はこれを全部いっぺんに使います。
つくるのは、お問い合わせフォームの入力チェックです。名前かメールアドレスが空のまま送信されたら、送信を止めてエラー文を出します。両方そろっていれば、エラーを消して受け付けたと表示します。
第2章で学んだ falsy が、ここでようやく本領を発揮します。空の入力欄の value は "" であり、"" は falsy です。つまり if (!name) と書くだけで「名前が入っていない」の判定になります。長さを数えたり空文字と比べたりする必要はありません。
空かどうかの判定
書き方はいくつかあります。どれも動きますが、読みやすさに差があります。
| 書き方 | 動くか | 評価 |
|---|---|---|
if (name === "") | 動く | 空白だけの入力を通してしまう |
if (name.length === 0) | 動く | 意味は同じだが 1 段まわりくどい |
if (!name) | 動く | 短く、falsy の考え方に沿っている |
すすめたいのは if (!name) ですが、これだけでは半角スペースを 1 つ打たれたときに通ってしまいます。空白は文字なので、" " は truthy です。そこで、読み取った直後に trim() を通します。
const nameValue = document.querySelector("#name").value.trim();trim() は文字列の前後の空白を取り除いて新しい文字列を返すメソッドです。" " を通すと "" になり、falsy として判定できるようになります。入力チェックでは value を読んだらすぐ trim()、と手が動くようにしておくと安全です。
trim()は元の文字列を変えません。新しい文字列を返します。だからvalue.trim()を書いても、画面の入力欄からスペースが消えることはありません。表示を整えたいならinput.value = input.value.trim()と入れ直す必要があります。
検証に落ちたら先へ進ませない
第6章で学んだ早期 return が、ここでそのまま使えます。
contactForm.addEventListener("submit", function (event) {
event.preventDefault();
const nameValue = document.querySelector("#name").value.trim();
const emailValue = document.querySelector("#email").value.trim();
if (!nameValue || !emailValue) {
formError.textContent = "お名前とメールアドレスを入力してください";
contactForm.classList.add("has-error");
formMessage.textContent = "";
return;
}
formError.textContent = "";
contactForm.classList.remove("has-error");
formMessage.textContent = "送信を受け付けました";
});条件は第3章の論理演算子です。|| は「どちらか一方でも当てはまれば」なので、名前が空でもメールが空でもエラーになります。両方そろっているときだけ、if を素通りして下の行に進みます。
return を書き忘れると、エラーを出したうえで受け付けたとも表示する、ちぐはぐな画面になります。落ちたらそこで抜ける、を徹底してください。
エラーは出すだけでなく、消す
入力チェックで見落としがちなのが、直したときにエラーが消えることです。エラーを出す処理だけを書いて、正常だったときに消す処理を書き忘れると、一度出たエラー文が画面に残り続けます。見ている人は、直したのに何が悪いのか分からないまま止まってしまいます。
今回は 2 つの方法で状態を表します。
- 文字 …
#form-errorのtextContentにエラー文を入れる。正常なら空文字に戻す - class …
.contact-formにhas-errorを付ける。正常なら外す
class のほうは CSS に用意してあり、付いている間だけ入力欄の枠が赤くなります。前回のダークモードと同じ考え方です。見た目は CSS が持ち、JavaScript は状態の名前を付け外しするだけにします。
エラーを出す場所も大事です。フォームのいちばん上や、送信ボタンのすぐそばなど、押した直後に目が向くところに置きます。画面の下のほうにあって、スクロールしないと見えないエラーは、出していないのとほとんど変わりません。今回は送信ボタンの真上に置きます。
また、エラー文には「何がいけないのか」と「どうすれば直るのか」を入れます。エラー の一言だけでは、見ている人は次の一手が分かりません。お名前とメールアドレスを入力してください のように、直し方まで書いておきます。
この検証は親切のためのもの
ひとつ大事なことを添えておきます。ブラウザで行う入力チェックは、見ている人に早く気付いてもらうためのものです。安全のためのものではありません。
ブラウザで動く JavaScript は、見ている人がいくらでも書き換えられます。検証の処理を消してから送ることもできます。ですから、実際にデータを受け取るサーバー側でも同じ検証をやり直します。ブラウザ側の検証は、往復の手間を減らして親切に伝えるためのもの、と位置付けてください。
| どこで検証するか | 目的 | 省いてよいか |
|---|---|---|
| ブラウザ | すぐ知らせて直してもらう | 省いても壊れないが不親切になる |
| サーバー | 不正なデータを受け付けない | 絶対に省けない |
この教材ではサーバーへ送るところまでは扱いませんが、「ブラウザの検証だけで安心してはいけない」という感覚だけは、いま持っておいてください。
今回書くこと
フォームの中、送信ボタンの上に id="form-error" の空の段落を足します。class="form-error" も付けてください。
JavaScript は、前回書いた submit の処理を書き換えます。新しく登録し直すのではなく、中身を差し替えてください。同じフォームに 2 つ登録すると、両方が動いてしまいます。
処理の流れは、先頭で preventDefault()、名前とメールを value.trim() で読み取り、どちらかが falsy ならエラー文と has-error を付けて return、そろっていればエラーを消して受け付けたと表示する、という順です。
よくある間違い
return を書き忘れる
if (!nameValue || !emailValue) {
formError.textContent = "入力してください";
}
formMessage.textContent = "送信を受け付けました";エラー文と受け付けた文が同時に出ます。if の中の最後に return; を置きます。
エラーを消す処理がない
if (!nameValue) {
formError.textContent = "入力してください";
return;
}
formMessage.textContent = "送信を受け付けました";一度出たエラー文が残ったままになります。正常だったときに formError.textContent = "" を書きます。
条件を && でつないでしまう
if (!nameValue && !emailValue) {これは「両方とも空のとき」です。片方だけ空のときは素通りしてしまいます。どちらか一方でも空なら止めたいので || を使います。
課題
- HTML の
.contact-formの中、送信ボタンのすぐ上にid="form-error"class="form-error"の空のpを足す - 前回書いた
submitの処理を書き換える。event.preventDefault()は先頭のまま残す #nameと#emailのvalueをtrim()して読み取り、どちらかが falsy ならエラー文を#form-errorに出し、.contact-formにhas-errorを付けてreturnする- 両方そろっているときは
#form-errorを空にし、has-errorを外して#form-messageに「送信を受け付けました」と出す