【问题标题】:Handling checkboxes in nested/hierarchial categories using jquery使用 jquery 处理嵌套/分层类别中的复选框
【发布时间】:2019-03-18 22:13:30
【问题描述】:

我有一个 WooCommerce 在线商店,我正在尝试让用户正确选择类别。

这个想法是,如果他们选择一个类别子类别,那么父类别也会被选择。

我已经这样做了,但是当取消选中子类别(并且没有检查输入)时,父级仍然处于选中状态。

$('ul.product_cat_list').find('input[type=checkbox]').each(function(index, input) {
  $(input).bind('change', function() {
    var checkbox = $(this);
    var is_checked = $(checkbox).is(':checked');
    if(is_checked) {
        $(checkbox).parents('li').children('input').attr('checked', 'checked');
    } else {
      $(checkbox).parentsUntil('ul').find('input').removeAttr('checked');
    }
  });
});

这里是Fiddle

【问题讨论】:

  • 尝试使用.prop('checked', true);.prop('checked', false);checked 是与属性相反的属性。
  • 这些场景很快变得复杂。您还需要考虑兄弟姐妹的检查状态。并且应该选中/取消选中父级选中/取消选中所有子级?
  • 您错过了将标题和复选框都包含在该标签中的绝佳机会。
  • @j08691 会考虑兄弟姐妹。选中/取消选中父级 选中/取消选中所有子级 no 是必要的。

标签: jquery checkbox


【解决方案1】:

查看您的标记如下是层次结构:

product_cat_list
    li
        input+ul.children
            li
                input+ul.children
                    li
                    li
                    li
                input+ul.children
                    li
                    li
                    input+ul.children
                        li
                        li
                            input+ul.children
                                li
                                li
                                li
                            input+ul.children
                                li
                                    input
                                li
                                    input
                                li
                                    input
                                li
                                    input
                        li
                    li
                input+ul.children
                    li
                    li
                    li
            li
            li
            li

    li 

我添加了更多级别以便运行测试。 在运行测试后,可以看到从起点重复执行相同的操作。所以你需要一个递归调用的函数。

    $(document).ready(function() {
      $("ul.product_cat_list input[type=checkbox]").on("change", function() {

        var checkboxValue = $(this).prop("checked");

        //call the recursive function for the first time
        decideParentsValue($(this));

        //Compulsorily apply check value Down in DOM
        $(this).closest("li").find(".children input[type=checkbox]").prop("checked", checkboxValue);


      });

      //the recursive function 
      function decideParentsValue(me) {
        var shouldTraverseUp = false;
        var checkedCount = 0;
        var myValue = me.prop("checked");

        //inspect my siblings to decide parents value
        $.each($(me).closest(".children").children('li'), function() {
          var checkbox = $(this).children("input[type=checkbox]");
          if ($(checkbox).prop("checked")) {
            checkedCount = checkedCount + 1;
          }
        });

        //if I am checked and my siblings are also checked do nothing
        //OR
        //if I am unchecked and my any sibling is checked do nothing
        if ((myValue == true && checkedCount == 1) || (myValue == false && checkedCount == 0)) {
          shouldTraverseUp = true;
        }
        if (shouldTraverseUp == true) {
          var inputCheckBox = $(me).closest(".children").siblings("input[type=checkbox]");
          inputCheckBox.prop("checked", me.prop("checked"));
          decideParentsValue(inputCheckBox);
        }

      }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="control unstyled product_cat_list">
  <li id="product_cat-51">
    <input value="51" type="checkbox" name="product_cat[]" id="in-product_cat-51">
    <label class="selectit">Accesorios</label>
    <ul class="children">

      <li id="product_cat-52">
        <input value="52" type="checkbox" name="product_cat[]" id="in-product_cat-52">
        <label class="selectit">Abanicos</label>
      </li>

      <li id="product_cat-53">
        <input value="53" type="checkbox" name="product_cat[]" id="in-product_cat-53">
        <label class="selectit">Bandoleras y riñoneras</label>
      </li>

      <li id="product_cat-246">
        <input value="246" type="checkbox" name="product_cat[]" id="in-product_cat-246">
        <label class="selectit">Billeteras</label>
      </li>

      <li id="product_cat-205">
        <input value="205" type="checkbox" name="product_cat[]" id="in-product_cat-205">
        <label class="selectit">Botones, pins</label>
      </li>

      <li id="product_cat-54">
        <input value="54" type="checkbox" name="product_cat[]" id="in-product_cat-54">
        <label class="selectit">Bufandas</label>
      </li>

      <li id="product_cat-342">
        <input value="342" type="checkbox" name="product_cat[]" id="in-product_cat-342">
        <label class="selectit">Cartucheras</label>
      </li>

      <li id="product_cat-55">
        <input value="55" type="checkbox" name="product_cat[]" id="in-product_cat-55">
        <label class="selectit">Chales y ponchos</label>
      </li>

      <li id="product_cat-56">
        <input value="56" type="checkbox" name="product_cat[]" id="in-product_cat-56">
        <label class="selectit">Cinturones</label>
        <ul class="children">

          <li id="product_cat-69">
            <input value="69" type="checkbox" name="product_cat[]" id="in-product_cat-69">
            <label class="selectit">Cinturones de hombre</label>
          </li>

          <li id="product_cat-70">
            <input value="70" type="checkbox" name="product_cat[]" id="in-product_cat-70">
            <label class="selectit">Cinturones de mujer</label>
          </li>

          <li id="product_cat-71">
            <input value="71" type="checkbox" name="product_cat[]" id="in-product_cat-71">
            <label class="selectit">Cinturones infantiles</label>
          </li>

          <li id="product_cat-72">
            <input value="72" type="checkbox" name="product_cat[]" id="in-product_cat-72">
            <label class="selectit">Cinturones unisex</label>
          </li>
        </ul>
      </li>

      <li id="product_cat-60">
        <input value="60" type="checkbox" name="product_cat[]" id="in-product_cat-60">
        <label class="selectit">Estuches, fundas</label>
      </li>

      <li id="product_cat-61">
        <input value="61" type="checkbox" name="product_cat[]" id="in-product_cat-61">
        <label class="selectit">Gorros, boinas y sombreros</label>
        <ul class="children">

          <li id="product_cat-78">
            <input value="78" type="checkbox" name="product_cat[]" id="in-product_cat-78">
            <label class="selectit">Gorros y boinas de fiesta</label>
          </li>

          <li id="product_cat-79">
            <input value="79" type="checkbox" name="product_cat[]" id="in-product_cat-79">
            <label class="selectit">Gorros y boinas de hombre</label>
          </li>

          <li id="product_cat-80">
            <input value="80" type="checkbox" name="product_cat[]" id="in-product_cat-80">
            <label class="selectit">Gorros y boinas deportivos y de playa</label>
          </li>

          <li id="product_cat-81">
            <input value="81" type="checkbox" name="product_cat[]" id="in-product_cat-81">
            <label class="selectit">Gorros y boinas infantiles</label>
          </li>

          <li id="product_cat-361">
            <input value="361" type="checkbox" name="product_cat[]" id="in-product_cat-361">
            <label class="selectit">Gorros y boinas para mujer</label>
          </li>

          <li id="product_cat-83">
            <input value="83" type="checkbox" name="product_cat[]" id="in-product_cat-83">
            <label class="selectit">Otros</label>
          </li>
        </ul>
      </li>

      <li id="product_cat-93">
        <input value="93" type="checkbox" name="product_cat[]" id="in-product_cat-93">
        <label class="selectit">Máscaras</label>
      </li>

      <li id="product_cat-63">
        <input value="63" type="checkbox" name="product_cat[]" id="in-product_cat-63">
        <label class="selectit">Mochilas</label>
      </li>

      <li id="product_cat-64">
        <input value="64" type="checkbox" name="product_cat[]" id="in-product_cat-64">
        <label class="selectit">Monederos y estuches</label>
      </li>

      <li id="product_cat-68">
        <input value="68" type="checkbox" name="product_cat[]" id="in-product_cat-68">
        <label class="selectit">Otros</label>
      </li>

      <li id="product_cat-65">
        <input value="65" type="checkbox" name="product_cat[]" id="in-product_cat-65">
        <label class="selectit">Pañuelos</label>
      </li>

      <li id="product_cat-802">
        <input value="802" type="checkbox" name="product_cat[]" id="in-product_cat-802">
        <label class="selectit">Para celulares</label>
      </li>

      <li id="product_cat-206">
        <input value="206" type="checkbox" name="product_cat[]" id="in-product_cat-206">
        <label class="selectit">Pipas, tabaqueras y cigarreras</label>
      </li>
    </ul>
  </li>
  <li id="product_cat-266">
    <input value="266" type="checkbox" name="product_cat[]" id="in-product_cat-266">
    <label class="selectit">Alimentos</label>
    <ul class="children">

      <li id="product_cat-267">
        <input value="267" type="checkbox" name="product_cat[]" id="in-product_cat-267">
        <label class="selectit">Adornos para torta</label>
        <ul class="children">

          <li id="product_cat-270">
            <input value="270" type="checkbox" name="product_cat[]" id="in-product_cat-270">
            <label class="selectit">Casamientos</label>
          </li>

          <li id="product_cat-271">
            <input value="271" type="checkbox" name="product_cat[]" id="in-product_cat-271">
            <label class="selectit">Cumpleaños</label>
          </li>
        </ul>
      </li>

      <li id="product_cat-268">
        <input value="268" type="checkbox" name="product_cat[]" id="in-product_cat-268">
        <label class="selectit">Cervecería</label>
      </li>

      <li id="product_cat-334">
        <input value="334" type="checkbox" name="product_cat[]" id="in-product_cat-334">
        <label class="selectit">Mermeladas y dulces</label>
      </li>

      <li id="product_cat-281">
        <input value="281" type="checkbox" name="product_cat[]" id="in-product_cat-281">
        <label class="selectit">Tortas decoradas</label>
      </li>

      <li id="product_cat-269">
        <input value="269" type="checkbox" name="product_cat[]" id="in-product_cat-269">
        <label class="selectit">Yerba</label>
      </li>
    </ul>
  </li>
</ul>

希望对你有帮助!

【讨论】:

  • 哇,这太接近他想要的了。但是我确实不需要在检查父类别时检查所有类别children,但是我看到如果我在代码中注释一行就解决了。
  • 是的,您可以评论该行。
  • 但是如果我去掉前面提到的功能:如果我取消选中父类别,孩子也应该取消选中。
  • 您可以通过添加条件轻松做到这一点:if(!checkboxValue){ $(this).closest("li").find(".children input[type=checkbox]")。 prop("选中",checkboxValue); }
【解决方案2】:

已编辑:

现在的解决方案是处理所有父母直到根:

handleChildren = function() {
  var $checkbox = $(this);
  var $checkboxChildren = $checkbox.parent().find(".children input[type=checkbox]");
  $checkboxChildren.each(function() {
    if ($checkbox.is(":checked")) {
      $(this).prop("checked", "checked");
    } else {
      $(this).removeProp("checked");
    }
  });
};
handleParents = function(current) {
  var $parent = $(current).closest(".children").closest("li").find("> input[type=checkbox]");
  if ($parent.parent().find(".children input[type=checkbox]:checked").length > 0) {
    $parent.prop("checked", "checked");
  } else {
    $parent.removeProp("checked");
  }
  handleParents($parent);
}

$('ul.product_cat_list').find('input[type=checkbox]').each(function(index, input) {
  $(input).on('click', handleChildren);
  $(input).on('click', function() {
    handleParents(this);
  });
});

小提琴:https://jsfiddle.net/diegopolido/040shgbg/4/

【讨论】:

  • 这成功了。但是,将复选标记冒泡到父级仅适用于一个嵌套级别。在您的小提琴中,检查 "Cinturones de hombre" 也会检查 "Cinturones" ,这很好。但由于 "Cinturones""Accesorios" 的子级,因此还应检查 "Accesorios"。它应该向上流动,直到您到达顶部。嵌套效果略有下降。请参阅其他答案以进行澄清。查看该示例时,请尝试选择嵌套两层的复选框。
  • 所以分叉并改进它;)
  • 我认为你没有抓住重点。答案在技术上是不完整的。它没有回答 OP 的问题。
  • Fixed ;) 现在所有父母都在处理直到根
【解决方案3】:

我根据 Diego 的代码添加了“不确定状态复选框”。

handleParents = function(current) {
  var $parent = $(current).closest(".children").closest("li").find("> input[type=checkbox]");
  if ($parent.parent().find(".children input[type=checkbox]:checked").length > 0) {
    if ($parent.parent().find(".children input[type=checkbox]:checked").length == $parent.parent().find(".children input[type=checkbox]").length) {
      $parent.prop("indeterminate", false);
      $parent.prop("checked", "checked");
    } else {
      $parent.prop("indeterminate", true);
    }
  } else {
    $parent.prop("indeterminate", false);
    $parent.removeProp("checked");
  }
  handleParents($parent);
}

小提琴:https://jsfiddle.net/wyysoft/xu0ev6wp/

【讨论】:

    猜你喜欢
    • 2019-04-17
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多