JavaScript | DOM 操作:フォーム操作 – バリデーション(required, pattern など)

JavaScript JavaScript
スポンサーリンク

バリデーションとは何か

バリデーションは「入力が条件を満たしているか」をチェックして、誤入力や欠落を防ぐ仕組みです。HTML とブラウザは、required・type・min/max・pattern などの属性だけで多くの検証を自動でやってくれます。ここが重要です:まずは“ブラウザ組み込みの検証”を最大限に活用し、その上で不足分のみ JavaScript で補うと、コードが短くて堅牢になります。


組み込みバリデーションの基本(required / type / min・max・step)

必須入力(required)

<input id="email" type="email" required placeholder="メールアドレス">
<script>
  // 送信時にブラウザが未入力を検出し、エラーバブルを表示
</script>
HTML

ここが重要です:required は「空を禁止」。submit 時に自動検出され、ブラウザがわかりやすいエラーを出します。動作はローカルで完結するので、JS がなくても安心です。

入力形式(type)

<input id="mail" type="email" required>
<input id="url"  type="url">
<input id="num"  type="number" min="0" step="1">
HTML

ここが重要です:type を正しく選ぶだけで、基本的な形式チェック(メール・URL・数値)が付きます。スマホではキーボードも適切に切り替わるため、入力体験も向上します。

範囲と刻み(min / max / step)

<input id="age" type="number" min="0" max="120" step="1" required>
HTML

ここが重要です:数値に“下限・上限・刻み”を設けられます。組み込み検証は「送信時に不正を止める」役割で、ロジック側でも Number(…) で数値化してから再検証するとさらに安全です。


パターン検証(pattern と title の活用)

正規表現で形式を限定する(半角英数字8〜16文字)

<input id="user" pattern="^[A-Za-z0-9]{8,16}$" title="半角英数字8〜16文字">
HTML

ここが重要です:pattern は入力全体に対する正規表現。ユーザーに“何が正しいか”を伝えるために title を必ずセットすると、エラー表示が分かりやすくなります。

日本語用の例(郵便番号 123-4567 または 1234567)

<input id="zip" inputmode="numeric" pattern="^\d{3}-?\d{4}$" title="例: 123-4567 または 1234567">
HTML

ここが重要です:記号の任意を「-?」で表現。inputmode=”numeric” を付けるとモバイルで数字キーボードが出て、打ちやすくなります。


組み込み検証の使い方(checkValidity / reportValidity / :invalid)

送信前に自前でチェック

<form id="f">
  <input name="email" type="email" required>
  <button>送信</button>
</form>
<script>
  f.addEventListener("submit", (e) => {
    if (!f.checkValidity()) {
      e.preventDefault(); // 送信を止める
      const firstInvalid = f.querySelector(":invalid");
      firstInvalid?.focus(); // 最初のエラーへフォーカス誘導
    }
  });
</script>
HTML

ここが重要です:checkValidity() は“すべての組み込み属性にもとづく検証”を一度に実行。失敗時は preventDefault で止め、:invalid 疑似クラスで最初の不正項目へフォーカスすると、再入力がスムーズです。

検証メッセージを画面に出す(reportValidity)

<script>
  // 任意のタイミングで “ブラウザ標準のバブル” を出す
  f.reportValidity(); // NG があれば、その場でエラーバブル表示
</script>
HTML

ここが重要です:reportValidity() はユーザーに見えるエラーを即表示。独自 UI を作らなくても、最短で親切なフィードバックが用意できます。

入力途中の見た目(CSS)

input:invalid { border-color: #d00; }
input:valid   { border-color: #0a0; }
CSS

ここが重要です::invalid/:valid を使うと、JSなしで視覚フィードバックが可能。過度な“赤警告”は入力途中のストレスになるので、確定後(blur)に強い色を当てるなどの配慮が有効です。


JavaScriptで不足分を補う(カスタム検証とセット)

独自ルールを足す(メール重複チェックなど)

<input id="mail" type="email" required>
<script>
  async function checkDuplicate(email) {
    // サーバーへ問い合わせる想定
    return false; // 重複なし(例)
  }
  mail.addEventListener("blur", async () => {
    const dup = await checkDuplicate(mail.value.trim());
    if (dup) {
      mail.setCustomValidity("このメールアドレスは既に利用されています");
    } else {
      mail.setCustomValidity(""); // エラー解除
    }
    mail.reportValidity();
  });
</script>
HTML

ここが重要です:setCustomValidity() は“組み込み検証に自前のメッセージを統合”する仕組み。空文字をセットすると解除されます。非同期検証は blur など確定寄りのタイミングにすると体験が安定します。

2項目の整合チェック(パスワード再入力)

<input id="pw"  type="password" required>
<input id="pw2" type="password" required>
<script>
  function syncConfirm() {
    if (pw2.value && pw2.value !== pw.value) {
      pw2.setCustomValidity("パスワードが一致しません");
    } else {
      pw2.setCustomValidity("");
    }
  }
  pw.addEventListener("input", syncConfirm);
  pw2.addEventListener("input", syncConfirm);
</script>
HTML

ここが重要です:相互依存の検証は“どちらかが変わったら両方再評価”。一致したら必ずエラー解除(空文字)を忘れずに。


バリデーションの設計指針(タイミング・メッセージ・アクセシビリティ)

いつ検証するか(入力中と確定後のメリハリ)

  • 入力中は軽いヒントや弱い表示(placeholder やヘルプ文)。
  • 確定後(blur)と送信前(submit)で強めのエラー表示。

ここが重要です:日本語入力(IME)中に厳しい検証や整形を走らせると体験が悪化します。compositionstart/compositionend を使って、確定後に本検証するのが安全です。

エラーメッセージは具体的に

  • 「形式が正しくありません」より「半角英数字8〜16文字です」のほうが修正しやすい。
  • pattern には必ず title を付け、検証理由を明示。

ここが重要です:ユーザーが“どう直せば良いか”をすぐ理解できるメッセージが、離脱や誤修正を減らします。

アクセシビリティの配慮

  • エラー時は最初の不正項目に focus()。
  • 可能なら aria-live でエラーテキストを読み上げ対応に。
  • 色だけに頼らず、テキストでも理由を示す。

ここが重要です:操作性と理解のしやすさを合わせて設計すると、誰にとっても使いやすいフォームになります。


実践例(検索フォーム、会員登録、住所入力)

検索フォーム(必須+最小文字数)

<form id="search">
  <input id="q" name="q" required minlength="2" placeholder="キーワード">
  <button>検索</button>
</form>
<script>
  search.addEventListener("submit", (e) => {
    if (!search.checkValidity()) {
      e.preventDefault();
      q.reportValidity();
      return;
    }
    // 検索処理へ
  });
</script>
HTML

ここが重要です:minlength は“テキストの下限”。短すぎる誤検索を防ぎ、ノイズを減らします。

会員登録(メール・パスワードの組み合わせ)

<form id="signup">
  <input id="mail" name="email" type="email" required>
  <input id="pw"   name="password" type="password" required pattern="^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$" title="英字と数字を含む8文字以上">
  <input id="pw2"  name="password2" type="password" required>
  <button>登録</button>
</form>
<script>
  function match() {
    pw2.setCustomValidity(pw2.value && pw2.value !== pw.value ? "パスワードが一致しません" : "");
  }
  pw.addEventListener("input", match);
  pw2.addEventListener("input", match);

  signup.addEventListener("submit", (e) => {
    if (!signup.checkValidity()) {
      e.preventDefault();
      signup.reportValidity();
    }
  });
</script>
HTML

ここが重要です:pattern で「強度の最低限」を担保し、再入力一致は custom validity で補う。役割分担が明確だと保守しやすいです。

住所入力(郵便番号での補助)

<form id="addr">
  <input id="zip" name="zip" inputmode="numeric" pattern="^\d{3}-?\d{4}$" required title="例: 123-4567">
  <input id="city" name="city" required>
  <button>送信</button>
</form>
<script>
  addr.addEventListener("submit", (e) => {
    if (!addr.checkValidity()) {
      e.preventDefault();
      addr.reportValidity();
      return;
    }
    // ここで zip から住所補完APIを呼ぶなどの拡張が可能
  });
</script>
HTML

ここが重要です:まずは形式を正しく、次に補助をかける。この順序なら「間違った値でAPIを叩く」無駄が減ります。


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

未入力と“空白だけ”を同一視してしまい、required を通過してしまうことがあります。送信前に trim() して空ならエラーにするルールを加えると安全です。pattern が「部分一致」になっていて、意図しない通過が起きるケースでは、^ と $ で“全体一致”にするのを忘れないでください。JavaScriptだけで全部検証しようとすると、モバイルキーボードやブラウザUIの恩恵を失いがちです。まず属性でできることを最大化し、不足だけ custom validity に寄せましょう。非同期検証(重複チェックなど)は入力途中に連発すると負荷・体験ともに悪化します。blur や submit 前にまとめて実施し、結果に応じて setCustomValidity → reportValidity の順で表示するのが安定します。


まとめ

バリデーションは「HTMLの組み込み属性で土台を作る」ことが最重要です。required・type・min/max・step・pattern を適切に使えば、送信前に多くの誤入力を自動で防げます。JavaScript は checkValidity/reportValidity で検証の流れを制御し、足りない部分を setCustomValidity で補完。タイミングは入力中は軽く、確定後と送信前に強く。メッセージは具体的に、フォーカス誘導やアクセシビリティも考える。これらを徹底すれば、初心者でも短いコードで“優しくて壊れない”フォーム検証を実装できます。

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