【问题标题】:Auto check/uncheck the "All" checkbox自动选中/取消选中“全部”复选框
【发布时间】:2025-12-09 19:10:02
【问题描述】:

我是 JS 新手,我有一个带有 2 个过滤器的页面,我被卡住了,我正在尝试:

  1. 如果过滤器的所有其他复选框都被选中,则自动选中(全部)复选框。

  2. 当用户取消选中某个复选框时,自动取消选中(全部)复选框。

我正在尝试以下代码,但它并没有真正工作......

HTML:

<div id="filter1">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F1: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F1: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F1: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F1: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>

<div id="filter2">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F2: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F2: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F2: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F2: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>

JS:

$(".checkboxlistitem").change(function() {
$(".select-all").prop("checked", $(".checkboxlistitem:checked").length ==    $(".checkboxlistitem").length);});

JSFIDDLE:

https://jsfiddle.net/Max06270/5scgbnww/

如果您需要澄清,请告诉我, 提前致谢, 最大

【问题讨论】:

  • 它不起作用怎么办?当我运行你的小提琴时,我看到的唯一我不想发生的事情是两个“全部”复选框都未选中。
  • 是的,这是第一件事。此外,如果您取消选择所有内容并一一选择复选框,除了(全部)之外,(全部)复选框不会被自己选中。
  • 这两个问题都在发生,因为您的过滤器对其元素使用相同的类。将它们拆分为使用单独的类将解决此问题,例如:class="select-all-1"class="select-all-2"。您还必须修改 checkboxlistitem 类并为您的其他过滤器及其类重复该 JS 函数。
  • 嗯...我的应用实际上有 15 个过滤器,我期待找到一个全局解决方案。感谢您的帮助

标签: javascript jquery html checkbox


【解决方案1】:

你的 jquery 选择器太通用了,所以它们影响了两种形式。下面应该是您想要的工作示例:

$(".select-all").change(function () {
    $(this).siblings().prop('checked', $(this).prop("checked"));
});

$(".checkboxlistitem").change(function() {
	  var checkboxes = $(this).parent().find('.checkboxlistitem');
    var checkedboxes = checkboxes.filter(':checked');

    if(checkboxes.length === checkedboxes.length) {
     $(this).parent().find('.select-all').prop('checked', true);
    } else {
    $(this).parent().find('.select-all').prop('checked', false);
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="filter1">
  <form action='#'>
    <input type="checkbox" value="all" class="select-all" checked>(All)<br>
    <input type="checkbox" value="v1" class="checkboxlistitem" checked>F1: Value1<br>
    <input type="checkbox" value="v2" class="checkboxlistitem" checked>F1: Value2<br>
    <input type="checkbox" value="v3" class="checkboxlistitem" checked>F1: Value3<br>
    <input type="checkbox" value="v4" class="checkboxlistitem" checked>F1: Value4<br>
    <input type="submit" value="Apply">
  </form> 
</div>

<br>

<div id="filter2">
  <form action='#'>
    <input type="checkbox" value="all" class="select-all" checked>(All)<br>
    <input type="checkbox" value="v1" class="checkboxlistitem" checked>F2: Value1<br>
    <input type="checkbox" value="v2" class="checkboxlistitem" checked>F2: Value2<br>
    <input type="checkbox" value="v3" class="checkboxlistitem" checked>F2: Value3<br>
    <input type="checkbox" value="v4" class="checkboxlistitem" checked>F2: Value4<br>
    <input type="submit" value="Apply">
  </form> 
</div>

https://jsfiddle.net/0epu6Lnn/

【讨论】:

  • 像魅力一样工作。非常感谢您的解决方案和解释!
【解决方案2】:

修复您的表单:

$('.checkboxlistitem')$('.checkboxlistitem:checked') 的选择器选择具有这些类的所有 元素,因此选择两种 形式的复选框。为了解决这个问题,他们需要上下文。

在 jQuery 的事件回调中,this 指的是触发事件的元素。这意味着我们可以使用相对选择器来找到合适的元素:

// find the nearest ancestor that's a form
$form = $(this).closest('form');

// find all the `.checkboxlistitem` elements within the form
$checkboxes = $form.find('.checkboxlistitem');

// find the all checkbox within the form
$all = $form.find('.select-all');

// if there are any unchecked checkboxes the all option should be unchecked
$all.prop('checked', !$checkboxes.not(':checked').length);

// leaving this as it was in the jsfiddle
// Select/Unselect all chexboxes of the form
$(".select-all").change(function () {
    $(this).siblings().prop('checked', $(this).prop("checked"));
});

$('.checkboxlistitem').change(function () {
  var $form,
      $checkboxes,
      $all;
  
  // find the nearest ancestor that's a form
  $form = $(this).closest('form');
  
  // find all the `.checkboxlistitem` elements within the form
  $checkboxes = $form.find('.checkboxlistitem');
  
  // find the all checkbox within the form
  $all = $form.find('.select-all');
  
  // if there are any unchecked checkboxes the all option should be unchecked
  $all.prop('checked', !$checkboxes.not(':checked').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="filter1">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F1: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F1: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F1: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F1: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>

<div id="filter2">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F2: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F2: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F2: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F2: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>

这很好,但让我们通过改进表单的可访问性和部分完整复选框列表的行为来提升一个档次。

表单可访问性

标签

您的复选框没有标签。

当然,您在它们之后添加了文本,但屏幕阅读器无法知道每个复选框代表什么。

要解决此问题,请使用 &lt;label&gt; 元素。

<form action="#">
  <label>
    <input type="checkbox" value="all" class="select-all" checked>
    (All)
  </label>
  <br>
  <label>
    <input type="checkbox" value="v1" class="checkboxlistitem" checked>
    F1: Value1
  </label>
  <br>
  ...
</form>

它们可以嵌套复选框,也可以将其[for] 属性指向&lt;input&gt; 元素的[id] 属性,或两者兼而有之。

<form action="#">
  <input type="checkbox" id="f1-all" value="all" class="select-all" checked> <label for="f1-all">(All)</label>
  <br>
  <input type="checkbox" id="f1-v1" value="v1" class="checkboxlistitem" checked> <label for="f1-v1">F1: Value1</label>
  <br>
  ...
</form>

层次结构

“全部”复选框和单个 F#: Value# 复选框之间存在不同的层次关系。

要解决此问题,请使用 &lt;fieldset&gt;&lt;legend&gt; 元素。

<form action="#">
  <fieldset>
    <legend>
      <label>
        <input type="checkbox" value="all" checked>
        <span>Select All in Filter 1</span>
      </label>
    </legend>
    <label>
      <input type="checkbox" value="v1" checked>
      <span>F1: Value1</span>
    </label>
    <br>
    ...
  </fieldset>
</form>

行分隔

您当前正在使用&lt;br&gt; 元素将字段分隔到不同的行。

&lt;p&gt; elements are often used.

<form action="#">
  <fieldset>
    <legend>...</legend>
    <p>
      <label>
        <input type="checkbox" value="v1" checked>
        <span>F1: Value1</span>
      </label>
    </p>
    ...
  </fieldset>
</form>

名字

您正在使用[value] 属性,这很好,但是&lt;input&gt; 元素都没有[name] 属性,这意味着数据不会发送到服务器,并调用jQuery 的@987654322表单上的 @ 不会为您提供适当的数据。

在具有重要值的复选框上设置[name](不需要“全部”复选框):

<form action="#">
  <fieldset>
    <legend>...</legend>
    <p>
      <label>
        <input type="checkbox" name="v1" value="1" checked>
        <span>F1: Value1</span>
      </label>
    </p>
    ...
  </fieldset>
</form>

或者,您可以将所有 [name] 属性设置为 filter 并依靠各种值来生成查询字符串,例如 filter=v1&amp;filter=v2,但这是一种高级技术,可能会遇到查询字符串解析的错误,所以请谨慎操作。

部分完整的复选框列表

虽然能够自动取消选中“所有”复选框,但当检查某些复选框并且未选中其他复选框时,未选中的状态并不完全有意义“所有”复选框。它不是“无”,也不是“全部”。

进入不确定状态

复选框有第三种状态,该状态只能通过 JavaScript 访问,正是为这种情况而设计的

您可以通过切换其indeterminate 属性将给定复选框设置为不确定状态:

document.querySelector('input[type="checkbox"]').indeterminate = true;

或使用 jQuery:

$('input[type="checkbox"]').first().prop('indeterminate', true);

可以通过以下区分来检查列表是否处于不确定状态:

  1. 未选中复选框
  2. 选中所有复选框
  3. 某些复选框已选中和未选中

实际上,这可能类似于:

checkedCount = $checkboxes.filter(':checked').length;

if (!checkedCount) {
  // no checkboxes checked
  $all.prop({
    checked: false,
    indeterminate: false
  });
} else if (checkedCount === $checkboxes.length) {
  // all checkboxes checked
  $all.prop({
    checked: true,
    indeterminate: false
  });
} else {
  // some checkboxes checked and unchecked
  $all.prop({
    indeterminate: true
  });
}

现在都在一起

上述所有内容的完整实现如下所示:

$('.filter').on('change', '[value="all"]', function () {
  var $form,
      $checkboxes,
      $all;
  
  $form = $(this).closest('form');
  $checkboxes = $form.find('[name="filter"]');
  $all = $form.find('[value="all"]');
  
  $checkboxes.prop('checked', $all.prop('checked'));
}).on('change', '[name="filter"]', function () {
  var $form,
      $checkboxes,
      $all,
      checkedCount;
  
  $form = $(this).closest('form');
  $checkboxes = $form.find('[name="filter"]');
  $all = $form.find('[value="all"]');
  
  checkedCount = $checkboxes.filter(':checked').length;
  
  if (!checkedCount) {
    // no checkboxes checked
    $all.prop({
      checked: false,
      indeterminate: false
    });
  } else if (checkedCount === $checkboxes.length) {
    // all checkboxes checked
    $all.prop({
      checked: true,
      indeterminate: false
    });
  } else {
    // some checkboxes checked and unchecked
    $all.prop({
      indeterminate: true
    });
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="filter1" class="filter">
  <form action='#'>
    <fieldset>
      <legend>
        <label>
          <input type="checkbox" value="all" checked>
          <span>Select All in Filter 1</span>
        </label>
      </legend>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v1" checked>
          <span>F1: Value1</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v2" checked>
          <span>F1: Value2</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v3" checked>
          <span>F1: Value3</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v4" checked>
          <span>F1: Value4</span>
        </label>
      </p>
    </fieldset>
    <input type="submit" value="Apply">
  </form>
</div>

<div id="filter2" class="filter">
  <form action='#'>
    <fieldset>
      <legend>
        <label>
          <input type="checkbox" value="all" checked>
          <span>Select All in Filter 2</span>
        </label>
      </legend>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v1" checked>
          <span>F2: Value1</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v2" checked>
          <span>F2: Value2</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v3" checked>
          <span>F2: Value3</span>
        </label>
      </p>
      <p>
        <label>
          <input type="checkbox" name="filter" value="v4" checked>
          <span>F2: Value4</span>
        </label>
      </p>
    </fieldset>
    <input type="submit" value="Apply">
  </form>
</div>

【讨论】:

  • 非常感谢您完整而详细的回答。阅读本文后,我对“表单最佳实践”有了更好的理解。我将实施它。再次感谢!
【解决方案3】:

对于那些想要使用 vanilla js 的人:

const checkboxes = document.getElementsByClassName("checkboxlistitem");
const selectAllBtn = document.getElementById("select-all");
for (let i = 0; i < checkboxes.length; i++) {
  checkboxes[i].addEventListener("change", () => {
    for (let i = 0; i < checkboxes.length; i++) {
      if (checkboxes[i].checked === false) {
        selectAllBtn.checked = false;
        break;
      } else {
        selectAllBtn.checked = true;
      }
    }
  });
}
// select all button

selectAllBtn.addEventListener("change", (event) => {
  for (let i = 0, n = checkboxes.length; i < n; i++) {
    checkboxes[i].checked = event.target.checked;
    
  }
});
<div id="filter1">
  <form action='#'>
    <input type="checkbox" value="all" id="select-all" checked>(All)<br>
    <input type="checkbox" value="v1" class="checkboxlistitem" checked>F1: Value1<br>
    <input type="checkbox" value="v2" class="checkboxlistitem" checked>F1: Value2<br>
    <input type="checkbox" value="v3" class="checkboxlistitem" checked>F1: Value3<br>
    <input type="checkbox" value="v4" class="checkboxlistitem" checked>F1: Value4<br>
    <input type="submit" value="Apply">
  </form> 
</div>

【讨论】: