2013-04-23 360 views
0

我试图在AngularJS中创建复选框的层次结构。我可以创建一个自动检查子复选框的父复选框,如果手动检查子复选框,它将更新其子('父母的孙子')复选框。但是,如果我点击父复选框,它不会更新孙子的复选框。AngularJS:孙子复选框从父复选框中选择

在我添加JavaScript以确保父复选框更新孙的复选框之前,我只想知道是否有更简单的方法。这是我的代码和一个jsFiddle为您的享受。

<div ng-app=""> 
    <strong>Parent</strong> (will check all Child boxes): 
    <input type="checkbox" ng-model="parent" /> 
    <br/> 
    <strong>Child 1</strong>: 
    <input type="checkbox" ng-checked="parent" /> 
    <br /> 
    <strong>Child 2</strong>: 
    <input type="checkbox" ng-checked="parent" /> 
    <br /> 
    <strong>Child 3</strong> (will check all Grandchild boxes): 
    <input type="checkbox" ng-checked="parent" ng-model="child" /> 
    <br /> 
    <strong>Grandchild 1</strong>: 
    <input type="checkbox" ng-checked="child" /> 
    <br /> 
    <strong>Grandchild 2</strong>: 
    <input type="checkbox" ng-checked="child" /> 
    <br /> 
    <strong>Grandchild 3</strong>: 
    <input type="checkbox" ng-checked="child" /> 
</div> 

任何帮助,将不胜感激!

另外,有1500名代表的人可以通过创建标签“angularjs-ng-checked”来帮助我吗?那太棒了!

+0

我最近写了这样的东西:http://jsfiddle.net/langdonx/hQqQV/2/。我只是使用模型,并通过一些数组迭代,看看是否一切都检查(而不是检查DOM元素)。请参阅'$ scope.groupChecked'和'_syncGroupCheckBox'(由'$ scope.unitChecked'调用)。 – Langdon 2013-04-23 17:29:52

+0

这可能会对JavaScript部分有所帮助,但在决定变得更加花哨之前,我对更简单的方法更感兴趣。尽管欣赏代码! – incutonez 2013-04-24 00:54:42

+0

不幸的是没有更简单的方法。这不能简单地通过HTML来完成。见米斯科的评论在这里:https://github.com/angular/angular.js/pull/1057 – Langdon 2013-04-24 13:47:26

回答

3

不幸的是没有简单的方法。

从MISKO via github

...我们认为你正在尝试做没有意义。 ng-checked创建单向数据绑定,但ng-model创建双向数据绑定。实质上,你有两个模型连接到相同的输入元素,我认为这是错误的。我认为ng-model和ng-checked应该独占使用,即一个或另一个但不在一起。

在控制器中使用指令或同步检查之外,没有太多的选项。

0

我一直在做一些摆弄(哈哈),我想出了一个解决方案,似乎很通用......意思是,你可以拥有尽可能多的嵌套复选框,因为你的心脏需要。我相信我会遵循一些奇怪的做法,并且可能会有一些领域的表现可能会增加 - 这绝对是通过很多对象循环 - 所以随时批评它!我很乐意听到任何反馈。

该代码可在此找到jsFiddle。我也会在这里发布。

的HTML

<!DOCTYPE html> 
<html> 
    <head> 
    <script src="../js/angularjs106.js"></script> 
    <script src="angular_checkbox.js"></script> 
    <link rel="stylesheet" href="angular_checkbox.css" /> 
    </head> 
    <body ng-app> 
    <div ng-controller="Ctrl"> 
     <ul> 
     <li> 
      <input type="checkbox" value="allChecks.id" ng-model="allChecks.isChecked" ng-change="checkChange(allChecks)"> 
      <label>{{allChecks.id}}</label> 
     </li> 
     <li ng-repeat="child in allChecks.children"> 
      <input type="checkbox" ng-model="child.isChecked" ng-change="checkChange(child)"> 
      <label>{{child.id}}</label> 
      <ul> 
      <li ng-repeat="grandchild in child.children"> 
       <input type="checkbox" ng-model="grandchild.isChecked" ng-change="checkChange(grandchild)"> 
       <label>{{grandchild.id}}</label> 
       <ul> 
       <li ng-repeat="grandgrandchild in grandchild.children"> 
        <input type="checkbox" ng-model="grandgrandchild.isChecked" ng-change="checkChange(grandgrandchild)"> 
        <label>{{grandgrandchild.id}}</label> 
       </li> 
       </ul> 
      </li> 
      </ul> 
     </li> 
     </ul> 
    </div> 
    </body> 
</html> 

JavaScript的

function Ctrl($scope) { 
    function Node(id, isChecked, parent) { 
    this.id = id; 
    this.isChecked = isChecked; 
    this.parent = parent; 
    this.children = []; 
    } 

    var parent = new Node('ALL', true, ""); 
    var child1 = new Node('Child 1', true, parent); 
    var gchild1 = new Node('Grandchild 1', true, child1); 
    var gchild2 = new Node('Grandchild 2', true, child1); 
    var gchild3 = new Node('Grandchild 3', true, child1); 
    child1.children.push(gchild1, gchild2, gchild3); 
    var child2 = new Node('Child 2', true, parent); 
    var child3 = new Node('Child 3', true, parent); 
    var child4 = new Node('Child 4', true, parent); 
    var gchild4 = new Node('Grandchild 4', true, child4); 
    var gchild5 = new Node('Grandchild 5', true, child4); 
    var gchild6 = new Node('Grandchild 6', true, child4); 
    var ggchild1 = new Node('Grandgrandchild 1', true, gchild6); 
    var ggchild2 = new Node('Grandgrandchild 2', true, gchild6); 
    var ggchild3 = new Node('Grandgrandchild 3', true, gchild6); 
    gchild6.children.push(ggchild1, ggchild2, ggchild3); 
    child4.children.push(gchild4, gchild5, gchild6); 
    var child5 = new Node('Child 5', true, parent); 
    parent.children.push(child1, child2, child3, child4, child5); 
    $scope.allChecks = parent; 

    function parentCheckChange(item) { 
    for (var i in item.children) { 
     item.children[i].isChecked = item.isChecked; 
     if (item.children[i].children) { 
     parentCheckChange(item.children[i]); 
     } 
    } 
    } 

    function childCheckChange(parent) { 
    var allChecks = true; 
    for (var i in parent.children) { 
     if (!parent.children[i].isChecked) { 
     allChecks = false; 
     break; 
     } 
    } 
    if (allChecks) { 
     parent.isChecked = true; 
    } 
    else { 
     parent.isChecked = false; 
    } 
    if (parent.parent) { 
     childCheckChange(parent.parent); 
    } 
    } 

    $scope.checkChange = function(item) { 
    // We're handling the ALL checkbox 
    if (item.id === $scope.allChecks.id) { 
     parentCheckChange(item); 
    } 
    // We're handling the toggling of all of the children here 
    else { 
     if (item.children) { 
     parentCheckChange(item); 
     } 
     childCheckChange(item.parent); 
    } 
    }; 
} 

微小的CSS

ul { 
    list-style: none; 
} 

无论如何,我想编辑找出找到对象中父项的方法。事实证明,原生JavaScript对象不包含对子对象的引用,所以我决定创建一个名为Node的类。当我实例化节点时,我可以将父项设置为包含子项的对象。一旦我这样做,递归变得相当容易。

parentCheckChange在我们意识到我们有父级时调用。 childCheckChange在孩子的支票变化(duh!)时被调用,但它被用来监视父母的所有孩子......如果它们都被选中,那么我们需要确保父项已被选中,并且由于这个父项已被选中,我们需要检查是否应该检查它的父项(递归)。

代码可能有点混乱,所以如果您感到困惑,请提问。