嵌套的父/子复选框 – 工作解决方案需要Bootstrap的调整帮助

我一直在寻找一个“完整”的解决方案来嵌套父子复选框,它可以根据层次结构正确地改变状态。

大多数“解决方案”不起作用或仅适用于一个级别。 它们还要求您以特定方式命名复选框。

这个 Stack Overflow讨论涵盖了要点,但也提供了Rory 在这里发现的一个很好的解决方案。

我已经在我的开发项目中对它进行了测试,它完全独立运行。 但是,我使用的是Bootstrap 2.x和复选框

我有一个JSFiddle ,它显示了工作示例代码,然后是我的版本,带有禁用的父复选框,然后是不起作用的bootsrap代码版本。

   Raw working example 


My initial code example - Is Working

  • Ford
    • Fiesta
    • Focus
    • Mondeo
  • Vauxhall
    • Corsa
    • Astra
    • Vectra

Bootstrap based code example - Not Working

 $(function () { // Apparently click is better chan change? Cuz IE? $('input[type="checkbox"]').change(function (e) { var checked = $(this).prop("checked"), container = $(this).parent(), siblings = container.siblings(); container.find('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); function checkSiblings(el) { var parent = el.parent().parent(), all = true; el.siblings().each(function () { return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked); }); if (all && checked) { parent.children('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); checkSiblings(parent); } else if (all && !checked) { parent.children('input[type="checkbox"]').prop("checked", checked); parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0)); checkSiblings(parent); } else { el.parents("li").children('input[type="checkbox"]').prop({ indeterminate: true, checked: false }); } } checkSiblings(container); }); }); 

我的理解是代码需要在某处更改为使用父母最近的代码 。 可以使用更好代码的人帮助确定需要在何处进行更改以使Bootstrap版本正常工作。

看看免费的JSTree用户控件。 它是基于JavaScript的开源,允许为多种样式的树视图配置,例如:

在此处输入图像描述

由于此处显示的复选框只是图像,因此您可以轻松地通过单选按钮替换它们,并且通过事件处理,您可以禁止多个选择,以便它们在需要时表现得像单选按钮。

这是通过如下指定"checkbox"插件来实现的(请参阅下面提供的完整工作代码片段):

 $(function () { $("#demo1") .jstree({ "themes": { "theme": "apple","dots": false,"icons": false }, "plugins": ["themes", "html_data", "checkbox", "sort", "ui"] }); }); 

相应的HTML结构如下所示,只需将其包含在页面正文中:

  

要获取选中的值,请使用此函数(假设您已创建一个id="listForDisplay"的div,就像我在JSFiddle示例中所做的那样):

 var $listForDisplay = $("#listForDisplay"); function displayList(data) { // see: https://www.jstree.com/docs/events/ var i, j, r = []; for (i = 0, j = data.selected.length; i < j; i++) { r.push(data.instance.get_node(data.selected[i]).text); } $listForDisplay.html('Selected: ' + r.join(', ')); } 

此代码可以在单击事件中触发,也可以像我一样绑定JSTree事件。 将以下内容附加到以前的JavaScript代码段可完成以下任务:

  $("#demo1") .on('loaded.jstree', function (e, data) { displayList(data); }) .on('change_state.jstree', function (e, data) { displayList(data); }); 

注意:选择父节点时,父名称将与子项一起列出。 如果仅选择了孩子,则不会列出相关的父母。

您可以在此处找到有关指定此插件行为的选项的更多信息。


可运行的代码片段(完整代码)

 $(function() { var $demo1 = $("#demo1"); var $listForDisplay = $("#listForDisplay"); function displayList(data) { // see: https://www.jstree.com/docs/events/ var i, j, r = []; for (i = 0, j = data.selected.length; i < j; i++) { r.push(data.instance.get_node(data.selected[i]).text); } $listForDisplay.html('Selected: ' + r.join(', ')); } $demo1.jstree({ "themes": { "theme": "apple", "dots": false, "icons": false }, "plugins": ["themes", "html_data", "checkbox", "sort", "ui"] }); $demo1.on('loaded.jstree', function(e, data) { displayList(data); }); $demo1.on('changed.jstree', function(e, data) { displayList(data); }); }); 
        

你可以尝试这样的事情

  $(function () { $('input[type="checkbox"]').change(function (e) { var checked = $(this).prop("checked"), container = $(this).closest("li"),//get closest li instead of parent siblings = container.siblings(); container.find('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); function checkSiblings(el) { var parent = el.parent().parent(), all = true, parentcheck=parent.children("label");//get the label that contains the disabled checkbox el.siblings().each(function () { return all = ($(this).find('input[type="checkbox"]').prop("checked") === checked); }); //use parentcheck instead of parent to get the children checkbox if (all && checked) { parentcheck.children('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); checkSiblings(parent); } else if (all && !checked) { parentcheck.children('input[type="checkbox"]').prop("checked", checked); parentcheck.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0)); checkSiblings(parent); } else { parentcheck.children('input[type="checkbox"]').prop({ indeterminate: true, checked: false }); } } checkSiblings(container); }); }); 

http://jsfiddle.net/Mvs87/2/