如何获得带有选择/取消选择所有功能和不确定值的 angular.js 复选框? [英] How can I get angular.js checkboxes with select/unselect all functionality and indeterminate values?
问题描述
我正在寻找与这些(带有父母"的三态复选框)完全相同的东西.但是使用该解决方案并不优雅,因为我现在不依赖于 jQuery,我需要调用 $scope.$apply 来让模型识别点击的自动(未)选中复选框的 jQuery.
这是 angular.js 的一个错误,要求实施 ng-indeterminate-value.但这仍然不能让我同步所有孩子,我认为这不应该成为我的控制器的一部分.
我正在寻找的是这样的:
- ng-children-model"指令的语法如下:
.将计算布尔值列表,如果选择 0 -> 复选框为 false.如果全部选中 -> 复选框为真.其他 -> 复选框不确定.
- 在我的控制器中,我会有这样的东西:
$scope.listelements = [{isSelected: true, desc: "Donkey"},{isSelected: false, desc: "Horse"}]
- 复选框将像往常一样使用
<tr ng-repeat="elem in listelements"><td><input type="checkbox" ng-model="elem.isSelected"></td><td>{{elem.desc}}</td></tr>
. - 据我所知,浏览器将确定点击的不确定复选框进入哪个状态.
由于您想要一种新类型/种类的组件,这听起来像是自定义指令的好例子.
由于父/主/三态复选框和单独的双态复选框需要相互交互,我建议使用带有自己的控制器的单个指令来处理逻辑.
指令:
app.directive('triStateCheckbox', function() {返回 {替换:真的,限制:'E',范围:{复选框:'='},模板:'<div><input type="checkbox" ng-model="master" ng-change="masterChange()">'+ '<div ng-repeat="cb in checkboxes">'+ '{{cb.desc}}'+ '</div>'+ '</div>',控制器:函数($scope,$element){$scope.masterChange = function() {如果($scope.master){angular.forEach($scope.checkboxes, function(cb, index){cb.isSelected = true;});} 别的 {angular.forEach($scope.checkboxes, function(cb, index){cb.isSelected = false;});}};var masterCb = $element.children()[0];$scope.cbChange = 函数(){var allSet = true, allClear = true;angular.forEach($scope.checkboxes, function(cb, index){如果(cb.isSelected){allClear = 假;} 别的 {allSet = 假;}});如果(所有集){$scope.master = true;masterCb.indeterminate = false;}否则如果(全部清除){$scope.master = false;masterCb.indeterminate = false;}别的 {$scope.master = false;masterCb.indeterminate = true;}};$scope.cbChange();//初始化},};});
更改模板以满足您的需要,或使用带有 templateUrl 的外部模板.
该指令假定 checkboxes 数组包含具有 isSelected
属性和 desc
属性的对象.
更新:如果您更喜欢让指令只呈现三态复选框,因此各个复选框都在 HTML 中(如@Piran 的解决方案),这里是 另一个plunker 变体.对于这个 plunker,HTML 将是:
</tri-state-checkbox>全选<div ng-repeat="列表元素中的项目"><input type="checkbox" ng-model="item.isSelected">{{item.desc}}
I am looking for something exactly like these (tri-state checkboxes with "parents"). But using that solution wouldn't be elegant, as I do not depend on jQuery right now, and I would need to call $scope.$apply to get the model to recognize the automatically (un)checked checkboxed jQuery clicked.
Here's a bug for angular.js that requests ng-indeterminate-value implemented. But that still wouldn't give me the synchronization to all the children, which is something I don't think should be a part of my controller.
What I am looking for would be something like this:
- A "ng-children-model" directive with syntax like:
<input type="checkbox" ng-children-model="child.isSelected for child in listelements">
. The list of booleans would be computed, and if 0 selected -> checkbox false. If all selected -> checkbox true. Else -> checkbox indeterminate. - In my controller, I would have something like this:
$scope.listelements = [{isSelected: true, desc: "Donkey"},{isSelected: false, desc: "Horse"}]
- The checkboxes would be made as usual with
<tr ng-repeat="elem in listelements"><td><input type="checkbox" ng-model="elem.isSelected"></td><td>{{elem.desc}}</td></tr>
. - As I understand it, the browser will determine which state a clicked indeterminate checkbox goes into.
Since you want a new type/kind of component, this sounds like a good case for a custom directive.
Since the parent/master/tri-stated checkbox and the individual dual-state checkboxes need to interact with each other, I suggest a single directive, with its own controller, to handle the logic.
<tri-state-checkbox checkboxes="listelements"></tri-state-checkbox>
Directive:
app.directive('triStateCheckbox', function() {
return {
replace: true,
restrict: 'E',
scope: { checkboxes: '=' },
template: '<div><input type="checkbox" ng-model="master" ng-change="masterChange()">'
+ '<div ng-repeat="cb in checkboxes">'
+ '<input type="checkbox" ng-model="cb.isSelected" ng-change="cbChange()">{{cb.desc}}'
+ '</div>'
+ '</div>',
controller: function($scope, $element) {
$scope.masterChange = function() {
if($scope.master) {
angular.forEach($scope.checkboxes, function(cb, index){
cb.isSelected = true;
});
} else {
angular.forEach($scope.checkboxes, function(cb, index){
cb.isSelected = false;
});
}
};
var masterCb = $element.children()[0];
$scope.cbChange = function() {
var allSet = true, allClear = true;
angular.forEach($scope.checkboxes, function(cb, index){
if(cb.isSelected) {
allClear = false;
} else {
allSet = false;
}
});
if(allSet) {
$scope.master = true;
masterCb.indeterminate = false;
}
else if(allClear) {
$scope.master = false;
masterCb.indeterminate = false;
}
else {
$scope.master = false;
masterCb.indeterminate = true;
}
};
$scope.cbChange(); // initialize
},
};
});
Change the template to suit your needs, or use an external template with templateUrl.
The directive assumes that the checkboxes array contains objects that have an isSelected
property and a desc
property.
Update: If you prefer to have the directive only render the tri-stated checkbox, hence the individual checkboxes are in the HTML (like @Piran's solution), here's another plunker variation for that. For this plunker, the HTML would be:
<tri-state-checkbox checkboxes="listelements" class="select-all-cb">
</tri-state-checkbox>select all
<div ng-repeat="item in listelements">
<input type="checkbox" ng-model="item.isSelected"> {{item.desc}}
</div>
这篇关于如何获得带有选择/取消选择所有功能和不确定值的 angular.js 复选框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!