チェックボックスの「全て選択」ボタンや、親チェックが変わると子チェックも変わる連動処理は、大量の選択肢を扱うフォームでよく使われます。この記事では全選択連動・親子チェック連動・トリプルステート(不確定状態)・フォーム送信時の処理まで解説します。
この記事でわかること
- 「全て選択」チェックボックスで一括選択・解除する
- 親チェックで子チェックを全て連動させる
- 子チェックの状態に応じて親チェックを自動更新する(トリプルステート)
- チェックボックスの値を取得してフォーム送信する
- 別の場所にある連動チェックの実装
「全て選択」で一括チェック・解除
<label><input type="checkbox" id="check-all"> 全て選択</label> <div id="item-list"> <label><input type="checkbox" class="item-check" value="apple"> りんご</label> <label><input type="checkbox" class="item-check" value="banana"> バナナ</label> <label><input type="checkbox" class="item-check" value="orange"> オレンジ</label> </div>
$(function () {
// 「全て選択」クリック → 子チェックを全て同じ状態にする
$('#check-all').on('change', function () {
$('.item-check').prop('checked', $(this).prop('checked'));
});
// 子チェックの変更 → 「全て選択」の状態を自動更新
$('.item-check').on('change', updateAllCheck);
function updateAllCheck() {
var total = $('.item-check').length;
var checked = $('.item-check:checked').length;
$('#check-all')
.prop('checked', checked === total)
.prop('indeterminate', checked > 0 && checked < total);
}
});
indeterminate(不確定状態)で中間状態を表現する
prop("indeterminate", true) を設定すると、チェックボックスがチェック済みでも未チェックでもない「中間」の見た目になります。UIの直感性が上がり、「一部選択中」であることがひと目でわかります。親子チェックの連動(ツリー構造)
<ul>
<li>
<label><input type="checkbox" class="parent-check" data-group="fruits"> 果物</label>
<ul>
<li><label><input type="checkbox" class="child-check" data-group="fruits" value="apple"> りんご</label></li>
<li><label><input type="checkbox" class="child-check" data-group="fruits" value="banana"> バナナ</label></li>
</ul>
</li>
<li>
<label><input type="checkbox" class="parent-check" data-group="vegs"> 野菜</label>
<ul>
<li><label><input type="checkbox" class="child-check" data-group="vegs" value="carrot"> にんじん</label></li>
</ul>
</li>
</ul>
$(function () {
// 親クリック → グループ内の子を全て連動
$('.parent-check').on('change', function () {
var group = $(this).data('group');
var checked = $(this).prop('checked');
$('[data-group="' + group + '"].child-check').prop('checked', checked);
});
// 子クリック → 親の状態を自動更新(indeterminate対応)
$('.child-check').on('change', function () {
var group = $(this).data('group');
var $children = $('[data-group="' + group + '"].child-check');
var total = $children.length;
var checked = $children.filter(':checked').length;
$('[data-group="' + group + '"].parent-check')
.prop('checked', checked === total)
.prop('indeterminate', checked > 0 && checked < total);
});
});
別の場所にあるチェックボックスを連動させる
フォームとは別の場所(例: サイドバー)にあるフィルターと、メインコンテンツのチェックを連動するパターンです。
<!-- サイドバーのフィルター --> <aside id="sidebar"> <input type="checkbox" id="sidebar-apple" data-target="main-apple"> りんご </aside> <!-- メインフォーム --> <form id="main-form"> <input type="checkbox" id="main-apple" name="items" value="apple"> りんご </form>
$(function () {
// サイドバーのチェック → メインのチェックを連動
$('#sidebar').on('change', 'input[type=checkbox]', function () {
var targetId = $(this).data('target');
$('#' + targetId).prop('checked', $(this).prop('checked'));
});
// メインのチェック → サイドバーも連動
$('#main-form').on('change', 'input[type=checkbox]', function () {
var id = $(this).attr('id');
$('[data-target="' + id + '"]').prop('checked', $(this).prop('checked'));
});
});
チェックされた値を取得してフォーム送信する
$(function () {
$('form').on('submit', function (e) {
e.preventDefault();
// チェックされた値を配列で取得
var selected = $('.item-check:checked').map(function () {
return $(this).val();
}).get();
if (selected.length === 0) {
alert('1つ以上選択してください');
return;
}
console.log('選択値:', selected); // ['apple', 'orange'] etc.
// Ajaxで送信
$.post('/api/save', { items: selected })
.done(function (data) {
console.log('送信成功');
});
});
});
まとめ
チェックボックス連動実装のポイントをまとめます。
- 全選択:
prop("checked", value)でまとめてセット - 中間状態:
prop("indeterminate", true)でトリプルステート - 親子連動:
data-groupでグループ管理 - 値取得:
$(".item:checked").map(fn).get()で配列化
関連記事: チェックボックスを操作する完全ガイド / ラジオボタンの操作完全ガイド / フォームバリデーション完全ガイド
よくある質問(FAQ)
Q動的に追加したチェックボックスに連動が効きません。
Aイベントデリゲーションを使います:
$(document).on("change", ".item-check", fn)直接バインドした $(".item-check").on("change", fn) はバインド後に追加された要素には効きません。Qチェックボックスをプログラムでチェックしてもchangeイベントが発火しません。
A
prop("checked", true) はDOMプロパティを変更しますが、changeイベントは自動発火しません。手動でイベントを発火させるには .trigger("change") を後に呼んでください:$("#checkbox").prop("checked", true).trigger("change")ただし無限ループに注意してください(連動先でもchangeが発火するため)。Qindeterminate 状態のチェックボックスはフォーム送信でどう扱われますか?
A
indeterminate はCSSの表示状態のみで、実際のチェック状態(true/false)は変わりません。フォーム送信時は checked プロパティの値(true/false)で判断されます。indeterminate のときは通常 checked === false であるため、未チェック扱いになります。Q全選択後に一部のチェックを外したとき「全て選択」も自動的に外れるようにしたいです。
A本記事の
updateAllCheck() 関数がまさにそのパターンです。子チェックの change イベントで全体の状態を再計算し、全チェック = true、一部チェック = indeterminate、ゼロ = false とします。Qチェックボックスの選択数に上限を設けたいです(最大3つまでなど)。
A
change イベントで選択数を確認し、上限を超えたらチェックを外します:if ($(".item-check:checked").length > 3) { $(this).prop("checked", false); }UIには何個まで選べるかを明示し、上限に達したら未チェックのオプションを disabled にするとよりわかりやすくなります。