複数回答チェックボックスで、1つ以上のチェックを必須にする方法

こんにちは。 エキサイト株式会社の三浦です。

こちらは、エキサイトホールディングス Advent Calendar 2023の18日目の記事になります。

qiita.com

良ければ他の記事もどうぞ!

さて、HTMLでフォームを作る際、「複数回答が用意されているチェックボックス式の設問に対して、最低1つ以上のチェックをしてもらいたい」という状況はよくあるでしょう。

今回はそういった場合に、コードにより1つ以上のチェックを必須にする方法を紹介します。

複数選択式チェックボックス

HTMLでフォームを作る場合、以下のような「複数回答が用意されているチェックボックス式の設問」を作ることはよくあるでしょう。

コードだと、以下のようになります。

なお簡単にするため、デザイン用のクラスやCSSは省略します。

<form method="POST" action="***">
    <div>どんな動物が好きですか?</div>

    <input id="animal-selection-dog"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-dog"
           value="犬"
    />
    <label for="animal-selection-dog"></label>

    <input id="animal-selection-cat"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-cat"
           value="猫"
    />
    <label for="animal-selection-cat"></label>

    <input id="animal-selection-crow"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-crow"
           value="カラス"
    />
    <label for="animal-selection-crow">カラス</label>

    <button type="submit">回答する</button>
</form>

これで設問の作成はできましたが、現状だと1つもチェックを入れていなくても問題なく回答できてしまいます。

ですが、実際は「1つ以上は必ずチェックして欲しい」という要件もよくあることでしょう。

では、「1つ以上のチェックを必須とする」にはどうすれば良いでしょうか。

1つ以上のチェックを必須にする方法:考えがちなミス

inputタグには、 required という属性があります。

それを使って以下のようにすれば良いのでは、と思う方も多いのではないでしょうか。

<!-- すべてのinputタグに required を追加 -->

<form method="POST" action="***">
    <div>どんな動物が好きですか?</div>

    <input id="animal-selection-dog"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-dog"
           value="犬"
           required
    />
    <label for="animal-selection-dog"></label>

    <input id="animal-selection-cat"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-cat"
           value="猫"
           required
    />
    <label for="animal-selection-cat"></label>

    <input id="animal-selection-crow"
            class="animal-selection"
            type="checkbox"
            name="animal-selection-crow"
            value="カラス"
            required
    />
    <label for="animal-selection-crow">カラス</label>

    <button type="submit">回答する</button>
</form>

では実際にこれで回答をしてみましょう。

なんと、すでに1つ以上の回答にチェックを入れているのにもかかわらず「チェックボックスをオンにしてください」と出てしまいました。

実は、チェックボックスは1つ1つのinputに対して required を判定するものであり、「1つ以上がチェックされているか」という判定は自動ではしてくれないのです。

では、どうすれば良いのでしょうか。

1つ以上のチェックを必須にする方法:正しい方法

残念ながら「1つ以上がチェックされているか」をHTMLだけで判定する方法は現状ありません。

JavaScriptを使うと良いでしょう。

<form method="POST" action="***">
    <div>どんな動物が好きですか?</div>

    <input id="animal-selection-dog"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-dog"
           value="犬"
           required
    />
    <label for="animal-selection-dog"></label>

    <input id="animal-selection-cat"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-cat"
           value="猫"
           required
    />
    <label for="animal-selection-cat"></label>

    <input id="animal-selection-crow"
           class="animal-selection"
           type="checkbox"
           name="animal-selection-crow"
           value="カラス"
           required
    />
    <label for="animal-selection-crow">カラス</label>

    <button type="submit">回答する</button>
</form>

<!-- 判定のため、JavaScriptを追加 -->
<script>
    (() => {
        // チェックボックスのinputタグを取得
        const checkBoxElements = Array.from(document.getElementsByClassName("animal-selection"));

        const errorMessage = "1つ以上の選択肢を選択してください。";
        checkBoxElements
            .forEach(m => {
                // エラーメッセージを、カスタムなものに変更
                m.setCustomValidity(errorMessage);

                // 各チェックボックスのチェックのオン・オフ時に、以下の処理が実行されるようにする
                m.addEventListener("change", () => {
                    // 1つ以上チェックがされているかどうかを判定
                    const isCheckedAtLeastOne = document.querySelector(".animal-selection:checked") !== null;

                    // 1つもチェックがされていなかったら、すべてのチェックボックスを required にする
                    // 加えて、エラーメッセージも変更する
                    checkBoxElements.forEach(n => {
                        n.required = !isCheckedAtLeastOne
                        n.setCustomValidity(isCheckedAtLeastOne ? "" : errorMessage);
                    });
                });
            });
    })();
</script>

少々コードが複雑に見えるかもしれませんが、やっていることは単純です。

  • 1つでもチェックが付いていたら、チェックボックスのinputタグ全てからrequired属性を排除
  • 1つもチェックが付いていなかったら、チェックボックスのinputタグ全てにrequired属性を追加
  • 加えて、エラーメッセージをカスタムなものに変更

これだけです。

実際にやってみると、以下のようになります。

もちろん、1つ以上チェックすれば問題なく回答することができます。

最後に

HTMLだけで複数回答チェックボックスの必須化をすることができないのは少々面倒ですが、それでも少しJavaScriptを加えれば対応可能です。

フォームを作成する上で必要になってくる場面も少なくないと思いますので、参考にしてもらえると幸いです!