JavaScript | DOM 操作:フォーム操作 – エラー表示の DOM 操作

JavaScript JavaScript
スポンサーリンク

エラー表示の DOM 操作とは何か

フォームの「どこが、なぜ、どう直せばいいか」を画面に明確に示すために、DOM(HTML構造)を動的に追加・更新・削除することです。ここが重要です:ブラウザ標準のバブル(reportValidity)は手軽ですが、レイアウトに合わせた見た目・位置・複数メッセージの管理には独自の DOM 操作が必要になります。入力直下に短いテキスト、フィールドグループの下に要約、フォーム上部に総合エラー、と“3段構え”にすると迷いが減ります。


最小構成のインラインエラー(入力の直下に出す)

コンパクトなパターン(1入力=1メッセージ)

<form id="f">
  <div class="field">
    <label for="mail">メール</label>
    <input id="mail" name="email" type="email" required>
    <small class="error" aria-live="polite"></small>
  </div>
  <button>送信</button>
</form>

<style>
  .field { margin-bottom: 12px; }
  .error { color:#d00; display:block; min-height:1em; }
  .invalid { border-color:#d00; }
</style>

<script>
  const f = document.getElementById("f");
  const mail = document.getElementById("mail");
  const err = f.querySelector(".error");

  function showError(input, message) {
    input.classList.toggle("invalid", Boolean(message));
    err.textContent = message || "";
  }

  mail.addEventListener("blur", () => {
    if (!mail.value.trim()) showError(mail, "メールは必須です");
    else if (!mail.checkValidity()) showError(mail, "メールの形式が正しくありません");
    else showError(mail, "");
  });

  f.addEventListener("submit", (e) => {
    if (!f.checkValidity()) {
      e.preventDefault();
      if (!mail.value.trim()) showError(mail, "メールは必須です");
      else if (!mail.checkValidity()) showError(mail, "メールの形式が正しくありません");
      mail.focus();
    }
  });
</script>
HTML

ここが重要です:小さな <small class="error"> を常設しておき、テキストを書き換えるだけにすると DOM の増減が少なく、スクリーンリーダーにも安定して伝えられます。空文字をセットして「消す」運用がシンプルです。


複数フィールドの管理(隣接要素・id連携・関数化)

共通の表示関数で整える

<form id="signup">
  <div class="field">
    <label for="pw">パスワード</label>
    <input id="pw" name="pw" type="password" required>
    <small id="pw-err" class="error" aria-live="polite"></small>
  </div>
  <div class="field">
    <label for="pw2">確認</label>
    <input id="pw2" name="pw2" type="password" required>
    <small id="pw2-err" class="error" aria-live="polite"></small>
  </div>
  <button>登録</button>
</form>

<script>
  const $ = (sel) => document.querySelector(sel);
  const pw = $("#pw"), pw2 = $("#pw2");
  const epw = $("#pw-err"), epw2 = $("#pw2-err");

  function setError(input, elError, msg) {
    input.classList.toggle("invalid", Boolean(msg));
    elError.textContent = msg || "";
  }

  function validatePw() {
    if (!pw.value.trim()) setError(pw, epw, "必須です");
    else if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(pw.value))
      setError(pw, epw, "英字と数字を含む8文字以上");
    else setError(pw, epw, "");
  }

  function validatePw2() {
    if (!pw2.value.trim()) setError(pw2, epw2, "必須です");
    else if (pw2.value !== pw.value) setError(pw2, epw2, "一致しません");
    else setError(pw2, epw2, "");
  }

  pw.addEventListener("input", () => { validatePw(); validatePw2(); });
  pw2.addEventListener("input", validatePw2);

  $("#signup").addEventListener("submit", (e) => {
    validatePw(); validatePw2();
    if ($(".invalid")) { e.preventDefault(); (pw.classList.contains("invalid") ? pw : pw2).focus(); }
  });
</script>
HTML

ここが重要です:表示関数を1つにまとめて「入力・エラーボックス・メッセージ」を渡す形にすると、項目が増えても再利用しやすく、スタイル連携も崩れません。相互依存(再入力一致)は両項目のイベントで再評価します。


アクセシビリティと読み上げ対応(aria 属性の要点)

画面読み上げへ正しく伝える

  • aria-live: エラー領域に aria-live=”polite” を付けると、更新時に読み上げが届きやすくなります。
  • aria-invalid:
    input.setAttribute(“aria-invalid”, “true”) をエラー時に付与、解除時は removeAttribute(“aria-invalid”)。
  • 関連付け:
    input.setAttribute(“aria-describedby”, “pw-err”) のように、エラーメッセージの要素 id を紐付ける。

ここが重要です:見た目の赤線だけに頼らず、支援技術へ「ここが間違い・理由はこれ」を伝えることで、誰にとっても修正しやすいフォームになります。


ブロック型のエラー要約(フォーム上部で総合表示)

一覧で見せると迷走が減る

<form id="f">
  <div id="summary" class="summary" aria-live="polite"></div>
  <!-- 以下、複数フィールド -->
</form>

<style>
  .summary { background:#fee; border:1px solid #d88; padding:8px; margin-bottom:12px; }
  .summary ul { margin:0; padding-left:18px; }
</style>

<script>
  function buildSummary(errors) {
    const s = document.getElementById("summary");
    if (!errors.length) { s.innerHTML = ""; return; }
    s.innerHTML = "<strong>入力エラー:</strong><ul>" +
      errors.map(e => `<li>${e}</li>`).join("") + "</ul>";
  }

  // 送信時に集計して要約を表示
  f.addEventListener("submit", (e) => {
    const errors = [];
    if (!mail.value.trim()) errors.push("メールは必須です");
    // …他の項目も追加
    if (errors.length) { e.preventDefault(); buildSummary(errors); }
  });
</script>
HTML

ここが重要です:上部に要約を出すと「何が間違いか」を一目で把握できます。フィールド直下には具体的な修正指示、要約には短文の一覧——役割分担が明快だと迷いません。


実践のコツ(タイミング・IME配慮・UIの一貫性)

いつ出すか(タイミングの設計)

  • 入力中(input):
    ヒント中心: 強い赤やアラートは避け、確定後に強める。
  • 確定後(blur):
    確実な検証: フォーマット・必須のエラーを出す。
  • 送信前(submit):
    総合判定: 全項目をチェックして、最初の不正へ focus。

ここが重要です:日本語入力の途中(compositionstart〜end)は確定していないため、強い整形・エラーは避けます。確定後に評価すると体験がスムーズです。

UIの一貫性を保つ

  • 色と構造:
    ガイドライン: 同じクラス名(.invalid, .error)で統一し、フィールド直下に同じ高さのメッセージ領域を置いてレイアウトのズレを防ぐ。
  • 文言の粒度:
    具体性: 「形式が不正」ではなく「半角英数字8〜16文字」のように“直し方”を明示。

ここが重要です:利用者は「どこが」「なぜ」「どう直す」を素早く知りたい。文言と見た目をパターン化すると迷わず修正できます。


よくある落とし穴と回避策

  • 見た目だけの赤線に頼る:
    文字説明と aria 属性で理由を伝える。色覚多様性にも配慮。
  • DOMを都度追加・削除してちらつく:
    事前に小さなエリアを常設し、textContent の切替にする。
  • IME途中で強制整形・警告を連発:
    composition イベントで合成中は検証を遅らせる。
  • フィールド外に出すだけのエラー要約で詳細がない:
    要約は短文、詳細は各フィールド直下。二層構造で迷いを減らす。
  • focus 誘導を忘れる:
    送信エラー時は最初の不正に focus()。修正速度が段違いに上がる。

まとめ

エラー表示の DOM 操作は「小さな常設エリアに文言を切り替える」のが基本で、入力直下・フォーム上部の要約・アクセシビリティ連携を組み合わせると強力です。タイミングは入力中は軽く、確定後と送信前に強く。ARIAと focus 誘導で操作性を高め、DOMの増減を抑えてちらつきを防ぐ。この設計を徹底すれば、初心者でも短いコードで“わかりやすく直しやすい”エラー表示が堅実に作れます。

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