Reputation: 119
What I'm trying to achieve is to check some checkboxes belonging to a ng-repeat
loop iteration when I check a "master" checkbox. My code so far in the view:
<div ng-app="CheckAllModule">
<div ng-controller="checkboxController">
<ul ng-repeat="s in struct">
<li><strong>{{s}} item</strong>
<input type="checkbox" ng-checked="x1 && x2 && x3" ng-model="selectedAll" ng-click="checkAll()" />
</li>
<label>Subitem A
<input type="checkbox" ng-checked="chk" ng-model="x1" />
</label>
<label>Subitem B
<input type="checkbox" ng-checked="chk" ng-model="x2" />
</label>
<label>Subitem C
<input type="checkbox" ng-checked="chk" ng-model="x3" />
</label>
</ul>
</div>
</div>
Where the first checkbox is the "master" and should impose its own state to the "slaves" (the next three checkboxes), no matter what was their previous state.
Regarding to the slave checkboxes, they should be checked & unchecked indepently. But If the three are checked at the same time, the master should be too. Whenever only one of them is not checked, the master shouldn't be as well.
And my controller:
var app = angular.module("CheckAllModule", []);
app.controller("checkboxController", function ($scope) {
$scope.struct = ['First', 'Second'];
$scope.checkAll = function () {
if ($scope.selectedAll) {
$scope.chk = true;
} else {
$scope.chk = false;
}
};
});
Upvotes: 2
Views: 1200
Reputation: 58425
This almost certainly doesn't follow best practices but I'm a noob with Angular. It does work though:
http://plnkr.co/edit/oGNC3ZUZHDHrBrMyRKjW?p=preview
var app = angular.module("CheckAllModule", []);
app.controller("checkboxController", function($scope) {
$scope.struct = ['First', 'Second'];
$scope.checkAll = function(selected, chkArray) {
for (var chk in chkArray) {
chkArray[chk] = selected
}
};
});
I made some adjustments to your html to get this working:
<div ng-app="CheckAllModule">
<div ng-controller="checkboxController">
<ul ng-repeat="s in struct" data-ng-init="x[1]=false;x[2]=false;x[3]=false">
<li>
<strong>{{s}} item</strong>
<input type="checkbox" ng-checked="x[1] && x[2] && x[3]" ng-model="selectedAll" ng-click="checkAll(selectedAll, x)" />
</li>
<label>Subitem A
<input type="checkbox" ng-model="x[1]" />
</label>
<label>Subitem B
<input type="checkbox" ng-model="x[2]" />
</label>
<label>Subitem C
<input type="checkbox" ng-model="x[3]" />
</label>
</ul>
</div>
</div>
Update
I was thinking about how better to test x1 && x2 && x3
the conversion to an array was the first step but then you can do:
x.indexOf(false)
(Ideally you would use .reduce(function(a,b) { return a && b; })
but reduce
is not yet well enough supported and to be fair, it's a bit more clunky) - strangely this is not working yet.
Upvotes: 3
Reputation: 8598
As a note, you should always try to bind to something using dot notation.
<ul ng-repeat="s in struct track by $index">
<li>
<strong>{{s.Item}} item</strong>
<input type="checkbox" ng-click="checkAll(s.selectedAll,$index)" ng-model="s.selectedAll" ng-checked="s.x1 && s.x2 && s.x3" />
</li>
<label>Subitem A
<input type="checkbox" ng-checked="s.chk" ng-model="s.x1" />
</label>
<label>Subitem B
<input type="checkbox" ng-checked="s.chk" ng-model="s.x2" />
</label>
<label>Subitem C
<input type="checkbox" ng-checked="s.chk" ng-model="s.x3" />
</label>
</ul>
The situation you have here is that you ng-repeat is bound to a list of strings. You should know that when repeating on a collection each item then would have it's own scope and maintain their values independently. This is hard to do since you can not add these values to a string (you need to bind to an object that can be expanded on).
I have made the adjustments that would allow for this particular setup. It should be agreeable as minor changes have been made.
Upvotes: 2