2013-04-23 362 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!)時被調用,但它被用來監視父母的所有孩子......如果它們都被選中,那麼我們需要確保父項已被選中,並且由於這個父項已被選中,我們需要檢查是否應該檢查它的父項(遞歸)。

代碼可能有點混亂,所以如果您感到困惑,請提問。