Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AngularJS 实现 checkbox 全选、反选的思考 #25

Open
mayufo opened this issue Aug 7, 2016 · 4 comments
Open

AngularJS 实现 checkbox 全选、反选的思考 #25

mayufo opened this issue Aug 7, 2016 · 4 comments

Comments

@mayufo
Copy link

mayufo commented Aug 7, 2016

需求

1 还有个总的 checkbox 负责全选和反选
2 当每一项开头都选中 checkbox 的时候,上面的全选自动选上
3 当全选后,取消其中一项的 checkbox ,全选取消

实践

我表示刚开始我是不会的!!!

思路1 上网查找 demo

然后开始查资料

发现个不错的网上案例 like this > demo

感觉非常符合我的需求,但是看到 demo。

缺点: 没玩几下就发现无法符合需求2、3。但是貌似1 是可以实现的。

思路2 ng-checked

开始查了下 checkbox 在 AngularJS 里面的用法和 ng-checked ,发现如果用了 ng-checked 目测可以实现

html

<div ng-controller="myController">
    <label for="flag">全选
        <input id="flag" type="checkbox" ng-model="select_all" ng-click="selectAll()">
    </label>
    <ul>
        <li ng-repeat="i in list">
            <input type="checkbox" ng-model="m[i.id]" ng-checked = "select_one" ng-click="selectOne(m[i.id])">
            <span>{{i.id}}</span>
        </li>
    </ul>
</div>

js

var app = angular.module('myApp',[]);
app.controller('myController', ['$scope', function ($scope) {
    $scope.list = [
        {'id': 101},
        {'id': 102},
        {'id': 103},
        {'id': 104},
        {'id': 105},
        {'id': 106},
        {'id': 107}
    ];
    $scope.m = [];
    $scope.checked = [];
    $scope.selectAll = function () {
        if($scope.select_all) {
            $scope.select_one = true;
            $scope.checked = [];
            angular.forEach($scope.list, function (i, index) {
                $scope.checked.push(i.id);
                $scope.m[i.id] = true;
            })
        }else {
            $scope.select_one = false;
            $scope.checked = [];
            $scope.m = [];
        }
        console.log($scope.checked);
    };
    $scope.selectOne = function (select) {
        angular.forEach($scope.m , function (i, id) {
            var index = $scope.checked.indexOf(id);
            if(i && index === -1) {
                $scope.checked.push(id);
            } else if (!i && index !== -1){
                $scope.checked.splice(index, 1);
            };
        });
        if ($scope.list.length === $scope.checked.length) {
            $scope.select_all = true;
        } else {
            $scope.select_all = false;
        }
        console.log($scope.checked);
    }
}]);

缺点 参考 not-binding-to-ng-checked-for-checkboxes

大概意思说 如果你用了 ng-checked 就是默认它最初定义就是 true, 因此就没有必要使用 ng-model 了。简单说来就是 ng-model 和 ng-checked 不需要同时用。

看来是能用 ng-click 或者 ng-change 了

思路3 给数组里面每一个 list 绑定 checked 的属性

这个想法也是联想到公司之前的一个大牛的写的一个关于 checkbox 的指令。

html

<div ng-controller="myController">
    <label for="flag">全选
        <input id="flag" type="checkbox" ng-model="select_all" ng-change="selectAll()">
    </label>
    <ul>
        <li ng-repeat="i in list">
            <input type="checkbox" ng-model="i.checked" ng-change="selectOne()">
            <span>{{id}}</span>
        </li>
    </ul>
</div>

js

var app = angular.module('myApp',[]);
app.controller('myController', ['$scope', function ($scope) {
    $scope.list = [
        {'id': 101},
        {'id': 102},
        {'id': 103},
        {'id': 104},
        {'id': 105},
        {'id': 106},
        {'id': 107}
    ];
    $scope.m = [];
    $scope.checked = [];
    $scope.selectAll = function () {
        if($scope.select_all) {
            $scope.checked = [];
            angular.forEach($scope.list, function (i) {
                i.checked = true;
                $scope.checked.push(i.id);
            })
        }else {
            angular.forEach($scope.list, function (i) {
                i.checked = false;
                $scope.checked = [];
            })
        }
        console.log($scope.checked);
    };
    $scope.selectOne = function () {
        angular.forEach($scope.list , function (i) {
            var index = $scope.checked.indexOf(i.id);
            if(i.checked && index === -1) {
                $scope.checked.push(i.id);
            } else if (!i.checked && index !== -1){
                $scope.checked.splice(index, 1);
            };
        })

        if ($scope.list.length === $scope.checked.length) {
            $scope.select_all = true;
        } else {
            $scope.select_all = false;
        }
        console.log($scope.checked);
    }
}]);

推荐第三种方法!以上

参考:

@hjzheng hjzheng changed the title angularjs实现 checkbox全选、反选的思考 AngularJS 实现 checkbox 全选、反选的思考 Aug 7, 2016
@hjzheng
Copy link
Member

hjzheng commented Aug 7, 2016

补充: 实现 checkbox 全选和反选的思路:
第一,由于后端数据不会提供一个空的 checkbox 列给我们,所以我们需要根据返回的长度初始化一个数组,并在 ng-repeat 的时候,赋值为 false。
第二,考虑到要为后端返回选中的 id 数组, 此时对相应的 checkbox 设置 ng-true-value="{{i.id}}"
第三,就是考虑,全选,反选的例子,其实很简单,全选的话,就为数组赋值所有的 id 数组,使用数组 map方法,反之,返回一个 false 数组
第四,当有 checkbox check 或 uncheck,你需要,改变控制全选和反选 checkbox 的行为,很简单使用 $watchCollection 方法监控数组变化,并使用数组 every 方法判断是否都不是 false 。

<div ng-app="myApp">
  <div ng-controller="myController">
      <label for="flag">全选
          <input id="flag" type="checkbox" ng-model="isAll" ng-click="checkAll()">
      </label>
      <ul>
          <li ng-repeat="i in list" ng-init="checkboxes[$index] = false">
              <input type="checkbox" ng-model="checkboxes[$index]" ng-true-value="{{i.id}}" ng-false-value="false">
              <span>{{i.id}}</span>
          </li>
      </ul>
      <button ng-click="getCheckedList()">get checked list</button>
  </div>
</div>
var app = angular.module('myApp',[]);

app.controller('myController', ['$scope', function ($scope) {

    $scope.list = [
        {'id': 101},
        {'id': 102},
        {'id': 103},
        {'id': 104},
        {'id': 105},
        {'id': 106},
        {'id': 107}
    ];

    $scope.checkboxes = new Array($scope.list.length);

    $scope.isAll = false;

    $scope.checkAll = function() {
         if ($scope.isAll) {
              $scope.checkboxes = $scope.list.map(function(item) {return item.id});
           } else {
              $scope.checkboxes = $scope.list.map(function(item) {return false});;
           }
    };

    $scope.$watchCollection('checkboxes', function(newC) {
          if (newC.every(function(item) {return item != false;})) {
              $scope.isAll = true;
          } else {
              $scope.isAll = false;
          }
    });

    $scope.getCheckedList = function() {
        alert($scope.checkboxes + ' ' +$scope.checkboxes.length );
        console.log($scope.checkboxes.filter(function(item) {return item;}));
    };

}]);

jsfiddle: https://jsfiddle.net/hjzheng/0nq252so/1/

@kuitos
Copy link

kuitos commented Aug 7, 2016

组件库带checkbox的表格有相应功能,可以参考

@kuitos
Copy link

kuitos commented Aug 7, 2016

不推荐第三种方法,原始数据引入脏属性,表单提交时可能需要额外处理

@nearxu
Copy link

nearxu commented Aug 25, 2016

选中的内容还要追加到一个input标签里面又该如何实现呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants