Helen Che
Helen Che

Reputation: 2011

Is it possible to disable all checkboxes after three ng-repeated checkboxes have been checked?

For example

 <input type="checkbox" ng-repeat="color in colors" 
                        ng-class="checked <= 3 ? '' : 'disabled'"/>

When I select an up to three checkboxes I want to disable the rest. What would be the angular way of doing this? Would I be able to keep everything "inline" or do I have to resort to filters/models?

Upvotes: 0

Views: 2392

Answers (3)

Michael Kang
Michael Kang

Reputation: 52847

I think this is what you are looking for:

var app = angular.module('app', []);
app.directive('checkboxes', function() {
  return {
    restrict: 'A',
    scope: {
      colors: '=checkboxes'
    },
    template: '<div ng-repeat="color in colors"><input type="checkbox" ng-disabled="count()>=3 && !color.checked" ng-model="color.checked" /> <span ng-class="{disabled:count()>=3 && !color.checked}">{{color.name}}</span></div>',
    controller: function($scope, $element) {
      function countChecked(arr, fn) {
        var checkCount = 0;
        for (var i = 0; i < arr.length; ++i) {
          if (fn(arr[i]) === true) {
            ++checkCount;
          }
        }

        return checkCount;
      }
      $scope.count = function() {
        return countChecked($scope.colors, function(color) {
          return color.checked;
        });
      }

    }
  }
});
app.controller('ctrl', function($scope) {

  $scope.colors = [{
    name: 'red'
  }, {
    name: 'green'
  }, {
    name: 'blue'
  }, {
    name: 'orange'
  }, {
    name: 'black'
  }];

});
.disabled {
  color: grey;
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="app" ng-controller="ctrl">
  <div checkboxes="colors">

  </div>
  Colors: {{colors}}
  <br />

</body>

Upvotes: 1

Peter Ashwell
Peter Ashwell

Reputation: 4302

I would bind some functions to the scope, since what you're doing is fairly complicated (depending on how the data is structured.

Check this out:

http://plnkr.co/edit/cfNGnx5eNXTuirCduWaG?p=preview

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.data = [
    {id: 'a', checked: false},
    {id: 'b', checked: false},
    {id: 'c', checked: true},
    {id: 'd', checked: true},
    {id: 'e', checked: false}
  ];
  $scope.selected = function() {
    var i, selectedCount = 0;
    for (i = 0; i < $scope.data.length; i++) {
      if ($scope.data[i].checked) {
        selectedCount += 1;
      }
    }
    return selectedCount;
  };
});

And the template:

<body ng-app="plunker" ng-controller="MainCtrl">
  <p>{{data | json}}</p>
  <p>Greater than 3? <span ng-bind="selected()"></span>
  </p>
  <label ng-repeat="elem in data">{{elem.id}}
    <input ng-disabled="selected() > 2 && !elem.checked" ng-model="elem.checked" type="checkbox" ng-checked="elem.checked">
  </label>
</body>

Upvotes: 1

Nitsan Baleli
Nitsan Baleli

Reputation: 5458

one way to achieve this, will be to assign ng-model to your checkboxes,
and have functions on the controller to determine how many of them are clicked, and if to disable the rest:

app.controller('MainCtrl', function($scope) {
  $scope.colors = ['red', 'blue', 'purple', 'yellow'];
  $scope.selected = [];
  $scope.check = function(color) {
    var pos = $scope.selected.indexOf(color);
    if (pos > -1) {
      $scope.selected.splice(pos,1);
    } else {
      $scope.selected.push(color);
    }
  } 

  $scope.disable = function(color) {
    return $scope.selected.length >= 3 && $scope.selected.indexOf(color) == -1;
  }
});

html:

<body ng-app ng-controller="MainCtrl">
  <input type="checkbox" ng-repeat="color in colors" ng-model="test" ng-change="check(color)" ng-disabled="disable(color)">
</body>

and a plnkr

Upvotes: 2

Related Questions