Reputation: 4781
I am having difficulties in understanding how to find out if some checkbox is selected or not in Angular.
This is the problem:
I have simple HTML table, on ng-change event I am calling one function that need to check if 'select all' checkbox is checked:
This is HTML:
<table class="table table-striped">
<thead>
<tr class="table-header">
<th ng-if="!newTestSessionCtrl.formData.battery.id"><input type="checkbox" ng-model="selectedAll" ng-change="newTestSessionCtrl.isSelectAll()" /></th>
<th>Test</th>
<th>Available Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in newTestSessionCtrl.formData.battery.testDefinitions">
<td ng-if="!newTestSessionCtrl.formData.battery.id"><input type="checkbox" ng-model="row.selected" ng-change="newTestSessionCtrl.isLabelChecked(); newTestSessionCtrl.validate()" /></td>
<td>{{row.name}}</td>
<td>{{(row.duration / 60) | number:0}} minutes</td>
</tr>
</tbody>
</table>
The name of model is: selectedAll
I have two functions, first one should be use for select all and deselect:
isSelectAll() {
let self = this;
self.model.selectedLabelList = [];
if(self.selectedAll) {
self.selectedAll = true;
for(var i=0; i < self.formData.battery.testDefinitions.length; i++) {
self.model.selectedLabelList.push(self.formData.battery.testDefinitions[i].name);
}
}
else {
self.selectedAll = false;
}
angular.forEach(self.formData.battery.testDefinitions, function(item) {
item.selected = self.selectedAll;
});
}
And the other one for un-checking 'select all' checkbox if one of the check boxes is deselected manual are this:
isLabelChecked() {
let self = this;
let _name = this.formData.battery.name;
if(this.formData.battery.selected) {
self.model.selectedLabelList.push(_name);
if(self.model.selectedLabelList.length == self.labelList.length ) {
self.selectedAll = true;
}
}else{
self.selectedAll = false;
let index = self.model.selectedLabelList.indexOf(_name);
self.model.selectedLabelList.splice(index, 1);
}
}
The problem is when defining selectedAll in js file.
I have constructor and if I do not define anything in it, selectedAll won't be in scope.
If I do this:
class NewTestSessionController {
constructor($scope, $state, resources, NewTestSessionService, formats, AuthenticationService, toastr, momentTimezone, _) {
this.model = {
selectedLabelList : []
};
this.selectedAll;
}
selectedAll will be in scope, but I will get 'false' value always. No matter if I have selected or deselected checkbox.
If I assign some value like this this.selectedAll = true
it won't be working correctly of course.
I have problem understanding why ng-model="selectedAll"
is not visible and how can I make it visible in js file, without using $scope
, since the main goal of my practice is to avoid usage of it.
Can someone see where I am making a mistake?
Upvotes: 3
Views: 1597
Reputation: 2106
var myapp = angular.module('sampleapp', []);
myapp.controller('samplecontoller', function ($scope) {
$scope.labelList = [
{ name: 'India' },
{ name: 'USA' },
{ name: 'Russia' },
{ name: 'China' },
{ name: 'Australia' },
{ name: 'Japan' }
]
$scope.model = {
selectedLabelList: []
}
$scope.isSelectAll = function () {
$scope.model.selectedLabelList = [];
if ($scope.master) {
$scope.master = true;
for (var i = 0; i < $scope.labelList.length; i++) {
$scope.model.selectedLabelList.push($scope.labelList[i].name);
}
}
else { $scope.master = false; }
angular.forEach($scope.labelList, function (item) {
item.selected = $scope.master;
});
}
$scope.isLabelChecked = function () {
var _name = this.label.name;
if (this.label.selected) {
$scope.model.selectedLabelList.push(_name);
if ($scope.model.selectedLabelList.length == $scope.labelList.length) { $scope.master = true; }
} else {
$scope.master = false;
var index = $scope.model.selectedLabelList.indexOf(_name);
$scope.model.selectedLabelList.splice(index, 1);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sampleapp" ng-controller="samplecontoller">
<input type="checkbox" ng-model="master" ng-change="isSelectAll()"><label>All Countries</label><br>
<li ng-repeat="label in labelList">
<input type="checkbox" ng-model="label.selected" ng-change="isLabelChecked()">
<label>{{ label.name }}</label>
</li>
</div>
This is example just fallow this code .
Upvotes: 2
Reputation: 283
Click here for best solution.
http://jsfiddle.net/TKVH6/2672/
HTML
<div ng-controller="checkboxController">
Check All
<input type="checkbox" ng-model="selectedAll" ng-click="checkAll()" />
<ul>
<li ng-repeat="item in Items">
<label>{{item.Name}}
<input type="checkbox" ng-model="item.Selected" />
</label>
</li>
</ul>
</div>
Script
angular.module("CheckAllModule", [])
.controller("checkboxController", function checkboxController($scope) {
$scope.Items = [{
Name: "Item one"
}, {
Name: "Item two"
}, {
Name: "Item three"
}];
$scope.checkAll = function () {
if ($scope.selectedAll) {
$scope.selectedAll = true;
} else {
$scope.selectedAll = false;
}
angular.forEach($scope.Items, function (item) {
item.Selected = $scope.selectedAll;
});
};
});
Upvotes: 2
Reputation: 1343
This is a common problem with AngularJS which uses prototypal inheritance between scopes.
ng-if
directive creates a new scope (call it $scope2) that inherit your controller's $scope.
In this new scope you can access selectedAll
, but if you assign it (the ng-model
directive does), the new value will be set on $scope2, and so $scope2.selectedAll will hide $scope.selectedAll.
Moreover, this.selectedAll;
has strictly no effect, you have to assign it to define the property.
To avoid these two issues, put selectedAll
in an object, and assign it, like this:
this.model.selectedAll = null;
and ng-model="model.selectedAll"
The reason why putting it in an object works is because assigning $scope2.model.selectedAll
will make JS resolve $scope2.model
, which refers to $scope.model
because $scope2
has no model
property (prototypal inheritance), and then define property selectedAll
on that $scope.model
.
When you do a.b.c.d = x
JS resolves a.b.c
object, and then assign x
to the property d
of that object.
Whithout model
, $scope2.selectedAll = true
defines the selectedAll
property on $scope2
, which hides the former $scope.selectedAll
.
Upvotes: 2