JavaScript requiredでフォーム必須入力を完全マスター!動的バリデーションの実装方法

javascript icon
JavaScript

こんにちは、とまだです。

フォームを作っていて、「この項目を必須にしたいけど、条件によって必須かどうか変えたい」と悩んだことはありませんか?

私も最初は、HTMLのrequired属性とJavaScriptをどう組み合わせればいいのか、本当に迷いました。

今回は、JavaScriptでrequired属性を自在に操る方法を、実例を交えながら徹底解説します。動的なフォームバリデーションが、思っているより簡単に実装できることをお伝えしますね。

JavaScript requiredとは?フォーム入力の必須制御を理解する

HTMLのrequired属性:まずは基本を押さえよう

JavaScriptでrequiredを操作する前に、HTMLの基本を確認しましょう。

required属性は、フォームの入力欄を必須項目にするHTML5の属性です。

<input type="text" name="username" required>

このように書くだけで、ブラウザが自動的に「この項目は必須ですよ」とチェックしてくれます。

身近な例で言うと、レストランの予約フォームを思い浮かべてください。

名前と電話番号は必須だけど、特別な要望は任意。これをHTMLで表現すると、このようになります。

<form>
  <input type="text" name="name" placeholder="お名前" required>
  <input type="tel" name="phone" placeholder="電話番号" required>
  <textarea name="request" placeholder="ご要望(任意)"></textarea>
  <button type="submit">予約する</button>
</form>

requiredが付いている項目を空のまま送信しようとすると、ブラウザがエラーメッセージを表示してくれます。

なぜJavaScriptでrequiredを操作する必要があるのか

「HTMLだけでできるなら、なぜJavaScriptが必要なの?」

そう思いますよね。

実は、実際のWebサービスでは状況に応じて必須項目が変わることがよくあるんです。

例えば、こんなケース:

配送先の選択

  • 「自宅に配送」を選んだら、住所入力は不要
  • 「別の住所に配送」を選んだら、住所入力が必須

会員登録フォーム

  • 「法人」を選んだら、会社名が必須
  • 「個人」を選んだら、会社名は不要

このような動的な制御は、HTMLだけでは実現できません。

JavaScriptの出番というわけです。

requiredエラーの仕組みと表示タイミング

required属性によるエラーチェックは、フォーム送信時に行われます。

エラーが発生すると、このようになります。

  1. フォームの送信がキャンセルされる
  2. 最初のエラー項目にフォーカスが移動
  3. エラーメッセージがポップアップ表示

ただし、このデフォルトの動作には制限があります。

  • エラーメッセージのデザインを変更できない
  • 表示位置を調整できない
  • 複数のエラーを同時に表示できない

だからこそ、JavaScriptでカスタマイズする価値があるんです。

JavaScriptでrequired属性を動的に追加・削除する基本テクニック

setAttribute()メソッドでrequiredを追加する方法

では、実際にJavaScriptでrequired属性を操作してみましょう。

最も基本的な方法はsetAttribute()メソッドです。

// 要素を取得
const emailInput = document.getElementById('email');

// required属性を追加
emailInput.setAttribute('required', '');

ポイントは、required属性の値は空文字列でOKということ。

HTMLの論理属性(boolean attribute)は、存在するだけで「true」を意味するんです。

removeAttribute()でrequiredを削除する実装例

required属性を削除する時はremoveAttribute()を使います。

// required属性を削除
emailInput.removeAttribute('required');

実践的な例を見てみましょう:

<label>
  <input type="checkbox" id="newsletter">
  ニュースレターを購読する
</label>
<input type="email" id="email" placeholder="メールアドレス">

<script>
const checkbox = document.getElementById('newsletter');
const emailInput = document.getElementById('email');

checkbox.addEventListener('change', function() {
  if (this.checked) {
    // チェックされたらメールアドレスを必須に
    emailInput.setAttribute('required', '');
  } else {
    // チェックを外したら必須を解除
    emailInput.removeAttribute('required');
  }
});
</script>

プロパティを使った簡潔な書き方

実は、もっと簡単な方法があります。

requiredプロパティを直接操作する方法です:

// required属性を追加
emailInput.required = true;

// required属性を削除
emailInput.required = false;

先ほどの例を書き直すと:

checkbox.addEventListener('change', function() {
  emailInput.required = this.checked;
});

たった1行で済みました!

どちらの方法を使うかは好みですが、私はプロパティを使う方法をおすすめします。

コードが短くて読みやすいからです。

実践的なJavaScript required活用パターン5選

パターン1:チェックボックスに連動した必須項目制御

よくある「その他」欄の実装を見てみましょう。

<form id="surveyForm">
  <p>好きなプログラミング言語は?</p>
  <label><input type="radio" name="lang" value="js"> JavaScript</label>
  <label><input type="radio" name="lang" value="python"> Python</label>
  <label><input type="radio" name="lang" value="other"> その他</label>

  <input type="text" id="otherLang" placeholder="言語名を入力" style="display: none;">

  <button type="submit">送信</button>
</form>

<script>
const radioButtons = document.querySelectorAll('input[name="lang"]');
const otherInput = document.getElementById('otherLang');

radioButtons.forEach(radio => {
  radio.addEventListener('change', function() {
    if (this.value === 'other') {
      otherInput.style.display = 'block';
      otherInput.required = true;
    } else {
      otherInput.style.display = 'none';
      otherInput.required = false;
      otherInput.value = ''; // 値もクリア
    }
  });
});
</script>

パターン2:選択値によって変わる必須フィールド

会員種別によって必須項目が変わるフォームです:

<form>
  <select id="memberType">
    <option value="">会員種別を選択</option>
    <option value="personal">個人会員</option>
    <option value="corporate">法人会員</option>
  </select>

  <div id="personalFields" style="display: none;">
    <input type="text" id="fullName" placeholder="氏名">
  </div>

  <div id="corporateFields" style="display: none;">
    <input type="text" id="companyName" placeholder="会社名">
    <input type="text" id="department" placeholder="部署名">
  </div>
</form>

<script>
const memberType = document.getElementById('memberType');
const personalFields = document.getElementById('personalFields');
const corporateFields = document.getElementById('corporateFields');

memberType.addEventListener('change', function() {
  // 全てのフィールドを一旦非表示&必須解除
  personalFields.style.display = 'none';
  corporateFields.style.display = 'none';

  document.getElementById('fullName').required = false;
  document.getElementById('companyName').required = false;
  document.getElementById('department').required = false;

  // 選択に応じて表示&必須設定
  if (this.value === 'personal') {
    personalFields.style.display = 'block';
    document.getElementById('fullName').required = true;
  } else if (this.value === 'corporate') {
    corporateFields.style.display = 'block';
    document.getElementById('companyName').required = true;
    document.getElementById('department').required = true;
  }
});
</script>

パターン3:複数条件を組み合わせた高度な制御

パスワードの確認フィールドを例に、複雑な条件を実装してみます:

const password = document.getElementById('password');
const confirmPassword = document.getElementById('confirmPassword');
const showPassword = document.getElementById('showPassword');

// パスワードが入力されたら確認も必須に
password.addEventListener('input', function() {
  confirmPassword.required = this.value.length > 0;
});

// パスワード表示時は確認不要
showPassword.addEventListener('change', function() {
  if (this.checked) {
    confirmPassword.required = false;
    confirmPassword.style.display = 'none';
  } else {
    confirmPassword.style.display = 'block';
    confirmPassword.required = password.value.length > 0;
  }
});

パターン4:エラーメッセージのカスタマイズ

デフォルトのエラーメッセージを変更する方法です:

const phoneInput = document.getElementById('phone');

phoneInput.addEventListener('invalid', function(e) {
  e.preventDefault(); // デフォルトの動作を停止

  if (this.validity.valueMissing) {
    this.setCustomValidity('電話番号は必須項目です');
  } else if (this.validity.patternMismatch) {
    this.setCustomValidity('正しい電話番号の形式で入力してください');
  }
});

// 入力時にカスタムメッセージをリセット
phoneInput.addEventListener('input', function() {
  this.setCustomValidity('');
});

パターン5:フォーム全体のバリデーション管理

最後に、フォーム全体を管理する実装パターンです:

class FormValidator {
  constructor(formId) {
    this.form = document.getElementById(formId);
    this.rules = new Map();
  }

  // ルールを追加
  addRule(fieldId, condition) {
    this.rules.set(fieldId, condition);
  }

  // 全てのルールを評価
  validate() {
    this.rules.forEach((condition, fieldId) => {
      const field = document.getElementById(fieldId);
      field.required = condition();
    });
  }
}

// 使用例
const validator = new FormValidator('myForm');

validator.addRule('email', () => {
  return document.getElementById('subscribe').checked;
});

validator.addRule('phone', () => {
  return document.getElementById('contactMethod').value === 'phone';
});

// 何かが変更されたら再評価
document.getElementById('myForm').addEventListener('change', () => {
  validator.validate();
});

よくあるエラーと解決方法

「required属性が効かない」問題の原因と対策

required属性を設定したのに効かない...よくある原因はこれらです:

1. フォーム要素の外にある

<!-- ❌ ダメな例 -->
<input type="text" required>
<button onclick="submit()">送信</button>

<!-- ✅ 良い例 -->
<form>
  <input type="text" required>
  <button type="submit">送信</button>
</form>

2. novalidate属性が設定されている

<!-- novalidateがあるとバリデーションが無効に -->
<form novalidate>
  <input type="text" required> <!-- 効かない! -->
</form>

3. JavaScriptでpreventDefault()している

// submitイベントを止めるとバリデーションも止まる
form.addEventListener('submit', (e) => {
  e.preventDefault(); // これがあるとrequiredチェックされない
});

タイミングの問題:DOMContentLoadedの重要性

要素が存在する前にJavaScriptが実行されるとエラーになります:

// ❌ ダメな例
const input = document.getElementById('myInput');
input.required = true; // エラー:inputがnull

// ✅ 良い例
document.addEventListener('DOMContentLoaded', () => {
  const input = document.getElementById('myInput');
  input.required = true; // OK!
});

ブラウザ互換性とポリフィルの考え方

required属性は主要ブラウザで広くサポートされていますが、古いブラウザでは使えません。

対策として、JavaScriptでフォールバック処理を実装できます:

// required属性がサポートされているかチェック
if (!('required' in document.createElement('input'))) {
  // サポートされていない場合の代替処理
  document.getElementById('myForm').addEventListener('submit', (e) => {
    const inputs = e.target.querySelectorAll('[required]');

    for (let input of inputs) {
      if (!input.value.trim()) {
        e.preventDefault();
        alert(input.placeholder + 'は必須項目です');
        input.focus();
        return;
      }
    }
  });
}

まとめ:JavaScript requiredで作る使いやすいフォーム

JavaScriptでrequired属性を操作する方法、いかがでしたか?

重要なポイントをまとめると:

  1. 基本はelement.required = true/falseで簡単に制御
  2. チェックボックスやセレクトボックスと連動させて動的に変更
  3. エラーメッセージもカスタマイズ可能
  4. フォーム要素内で使うことを忘れずに

最初は複雑に感じるかもしれませんが、一つずつ試していけば必ず理解できます。

もっと体系的にJavaScriptを学びたい方は、JavaScript学習完全ガイドもぜひご覧ください。

フォームは、ユーザーとWebサイトをつなぐ大切な接点です。

required属性を上手に使って、ユーザーに優しいフォームを作っていきましょう!

共有:

著者について

とまだ

とまだ

フルスタックエンジニア

Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。

著者の詳細を見る →