我正在尝试在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 :(得分:3)
不幸的是,没有更简单的方法。
来自Misko via github:
...我们认为你要做的事情没有意义。 ng-checked创建单向数据绑定,但ng-model创建双向数据绑定。从本质上讲,你有两个模型连接到同一个输入元素,我认为这是错误的。我认为ng-model和ng-checked应该是专门使用的,即一个或另一个但不能一起使用。
除了使用指令或在控制器中自己同步检查之外,没有很多选项。
答案 1 :(得分: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的类。当我实例化Node时,我可以将父设置为包含子节点的对象。一旦我这样做,递归变得非常容易。
当我们意识到我们有父母时,会调用parentCheckChange。当孩子的检查发生变化时,会调用childCheckChange(呃!),但它用于监视所有父母的孩子......如果检查了所有孩子,那么我们需要确保检查父母,并且因为这个已检查父级,我们需要检查是否应检查其父级(递归)。
代码可能有点令人困惑,所以如果您感到困惑,请提出问题!