如何获得带有选择/取消选择所有功能和不确定值的 angular.js 复选框? [英] How can I get angular.js checkboxes with select/unselect all functionality and indeterminate values?

查看:22
本文介绍了如何获得带有选择/取消选择所有功能和不确定值的 angular.js 复选框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找与这些(带有父母"的三态复选框)完全相同的东西.但是使用该解决方案并不优雅,因为我现在不依赖于 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 属性的对象.

Plunker.

更新:如果您更喜欢让指令只呈现三态复选框,因此各个复选框都在 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.

Plunker.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆