JavaScript | ゼロからはじめるプログラミング、30日で基礎を学ぶJavaScript:Webページを操作できるようになる - Day19.5:条件 + DOM応用

JavaScript JavaScript
スポンサーリンク

Day19.5 前半のゴール

Day19.5 は、Day19 までに学んだ「入力チェック」「条件分岐」「DOM 操作」を
もう一段レベルアップさせて、“ちょっと複雑なフォーム”を扱えるようになる日です。

前半のゴールはこうです。

前半で身につけたい感覚

複数項目・複数条件を「整理して」チェックする

入力チェックのロジックと「表示の更新」を頭の中で分けて考える

「通していい状態かどうか」を最後に一括で判断する


複雑なフォーム処理とは何か

「項目が増える」と一気にごちゃつく

名前だけ、年齢だけをチェックしていたときは、
if を数個書くだけで済みました。

でも、現実のフォームはもっと欲張りです。

ユーザー名
メールアドレス
パスワード
パスワード(確認用)
利用規約に同意したかどうか

こういった複数の項目を、
それぞれ別のルールでチェックし、
エラーがあればユーザーに分かりやすく伝える必要があります。

ここで大事になるのが、

「チェックのロジックを整理する」
「エラーの管理方法を決める」

という視点です。


例題フォームを決める

会員登録フォーム風の例を使う

前半では、次のようなフォームを題材にします。

<form id="registerForm">
  <p>
    ユーザー名:<input id="userInput" type="text">
  </p>
  <p>
    メールアドレス:<input id="emailInput" type="text">
  </p>
  <p>
    パスワード:<input id="passwordInput" type="password">
  </p>
  <p>
    パスワード(確認):<input id="passwordConfirmInput" type="password">
  </p>
  <p>
    <label>
      <input id="termsCheckbox" type="checkbox">
      利用規約に同意します
    </label>
  </p>
  <button type="submit">登録</button>
</form>

<p id="message"></p>

チェックしたい条件をざっくり挙げるとこうなります。

ユーザー名:空でない、20文字以内
メール:空でない、最低限「@」を含む
パスワード:空でない、8文字以上
パスワード確認:パスワードと一致している
利用規約:チェックされている

これを、ぐちゃぐちゃにならないように if と DOM で組み立てていきます。


まずは「全体の流れ」を決める

submit イベントを入口にする

フォームなので、submit イベントを使います。

const registerFormElement = document.getElementById("registerForm");
const userInputElement = document.getElementById("userInput");
const emailInputElement = document.getElementById("emailInput");
const passwordInputElement = document.getElementById("passwordInput");
const passwordConfirmInputElement = document.getElementById("passwordConfirmInput");
const termsCheckboxElement = document.getElementById("termsCheckbox");
const messageElement = document.getElementById("message");

registerFormElement.addEventListener("submit", (event) => {
  event.preventDefault();

  const user = userInputElement.value.trim();
  const email = emailInputElement.value.trim();
  const password = passwordInputElement.value;
  const passwordConfirm = passwordConfirmInputElement.value;
  const termsChecked = termsCheckboxElement.checked;

  messageElement.textContent = "";

  // ここから入力チェックを書いていく
});
JavaScript

ここまででやっていることはシンプルです。

フォーム送信を submit で受け取る
preventDefault でページ遷移を止める
各 input / checkbox から値を取得する
メッセージ表示用の要素を一旦リセットする

この「入口の形」をまず固定してしまうと、
あとは中身のチェックロジックに集中できます。


エラーを配列で管理する

「どこがダメか」をためていく箱を用意する

複雑なフォームでは、
「エラーが1つだけ」とは限りません。

そこで、エラーメッセージを配列で管理します。

registerFormElement.addEventListener("submit", (event) => {
  event.preventDefault();

  const user = userInputElement.value.trim();
  const email = emailInputElement.value.trim();
  const password = passwordInputElement.value;
  const passwordConfirm = passwordConfirmInputElement.value;
  const termsChecked = termsCheckboxElement.checked;

  const errors = [];

  if (user === "") {
    errors.push("ユーザー名を入力してください。");
  } else if (user.length > 20) {
    errors.push("ユーザー名は20文字以内で入力してください。");
  }

  if (email === "") {
    errors.push("メールアドレスを入力してください。");
  } else if (!email.includes("@")) {
    errors.push("メールアドレスの形式が正しくありません。");
  }

  if (password === "") {
    errors.push("パスワードを入力してください。");
  } else if (password.length < 8) {
    errors.push("パスワードは8文字以上で入力してください。");
  }

  if (passwordConfirm === "") {
    errors.push("パスワード(確認)を入力してください。");
  } else if (password !== passwordConfirm) {
    errors.push("パスワードと確認用パスワードが一致しません。");
  }

  if (!termsChecked) {
    errors.push("利用規約に同意してください。");
  }

  if (errors.length > 0) {
    messageElement.textContent = errors.join(" ");
    return;
  }

  messageElement.textContent = "登録が完了しました。";
});
JavaScript

ここでの重要ポイントはこうです。

条件ごとに errors.push(…) でメッセージを追加する
最後に errors.length を見て、「通していい状態か」を判断する
エラーがあればまとめて表示し、return で処理を止める

「途中で return して終わり」ではなく、
「全部チェックしてから判断する」スタイルになっているのが、
複雑なフォーム処理の特徴です。


条件を整理して読むコツ

「項目ごと」にブロックを分けて考える

上のコードを読むときは、
if を一行ずつ追うのではなく、項目ごとに塊として読むと楽になります。

ユーザー名のブロック
メールのブロック
パスワードのブロック
パスワード確認のブロック
利用規約のブロック

というふうに、
「この塊はユーザー名のルール」「この塊はメールのルール」と
頭の中でラベリングして読むと、
条件が増えても怖くなくなります。


チェックボックスの扱いを深掘りする

checked プロパティは true / false

利用規約のチェックボックスは、
value ではなく checked プロパティを使います。

const termsChecked = termsCheckboxElement.checked;

if (!termsChecked) {
  errors.push("利用規約に同意してください。");
}
JavaScript

checked は真偽値(boolean)です。

チェックされていれば true
外れていれば false

if (!termsChecked) は
「チェックされていないなら」という意味になります。

ここでのポイントは、
「input の種類によって、見るべきプロパティが違う」ということです。

text / password など:value
checkbox:checked

この違いを意識できると、フォーム操作の理解が一段深くなります。


エラーがないときだけ「次の処理」に進む

「通していい状態かどうか」を最後に一括で判断する

複雑なフォームでは、
「全部のチェックを通過したときだけ、次の処理に進む」
という形が基本です。

さきほどのコードでは、
errors.length > 0 のときに return していました。

if (errors.length > 0) {
  messageElement.textContent = errors.join(" ");
  return;
}

messageElement.textContent = "登録が完了しました。";
JavaScript

この「最後に一括で判定する」スタイルを身につけると、
後で「サーバーに送信する処理」や「画面遷移する処理」を追加するときも、
とても書きやすくなります。


Day19.5 前半のミニサンプル

ここまでをまとめたシンプル版

少しだけ簡略化した形で、もう一度全体を通してみます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Day19.5 条件 + DOM 応用 前半</title>
  </head>
  <body>
    <h1>会員登録フォーム(前半版)</h1>

    <form id="registerForm">
      <p>
        ユーザー名:<input id="userInput" type="text">
      </p>
      <p>
        メールアドレス:<input id="emailInput" type="text">
      </p>
      <p>
        パスワード:<input id="passwordInput" type="password">
      </p>
      <p>
        パスワード(確認):<input id="passwordConfirmInput" type="password">
      </p>
      <p>
        <label>
          <input id="termsCheckbox" type="checkbox">
          利用規約に同意します
        </label>
      </p>
      <button type="submit">登録</button>
    </form>

    <p id="message"></p>

    <script>
      const registerFormElement = document.getElementById("registerForm");
      const userInputElement = document.getElementById("userInput");
      const emailInputElement = document.getElementById("emailInput");
      const passwordInputElement = document.getElementById("passwordInput");
      const passwordConfirmInputElement = document.getElementById("passwordConfirmInput");
      const termsCheckboxElement = document.getElementById("termsCheckbox");
      const messageElement = document.getElementById("message");

      registerFormElement.addEventListener("submit", (event) => {
        event.preventDefault();

        const user = userInputElement.value.trim();
        const email = emailInputElement.value.trim();
        const password = passwordInputElement.value;
        const passwordConfirm = passwordConfirmInputElement.value;
        const termsChecked = termsCheckboxElement.checked;

        const errors = [];

        if (user === "") {
          errors.push("ユーザー名を入力してください。");
        }

        if (email === "") {
          errors.push("メールアドレスを入力してください。");
        }

        if (password === "") {
          errors.push("パスワードを入力してください。");
        }

        if (passwordConfirm === "") {
          errors.push("パスワード(確認)を入力してください。");
        } else if (password !== passwordConfirm) {
          errors.push("パスワードと確認用パスワードが一致しません。");
        }

        if (!termsChecked) {
          errors.push("利用規約に同意してください。");
        }

        if (errors.length > 0) {
          messageElement.textContent = errors.join(" ");
          return;
        }

        messageElement.textContent = "登録が完了しました。";
      });
    </script>
  </body>
</html>

ここまで書ければ、
「複数項目・複数条件のフォームを、整理してチェックする」
という Day19.5 前半のテーマは、かなりいいところまで来ています。


Day19.5 前半のまとめ

前半で押さえたかったのは、テクニックそのものよりも「考え方」です。

フォーム全体を submit で受ける
各 input / checkbox から値を取り出す
エラーを配列で管理し、条件ごとに追加していく
最後に errors.length を見て、「通していい状態か」を一括で判断する

後半ではここに、
エラーごとに見た目を変える
バリデーションロジックを関数に分離する
「成功時の処理」と「失敗時の処理」をきれいに分ける

といった要素を足して、
より“本番に近い”複雑フォーム処理に仕上げていきます。

タイトルとURLをコピーしました