Reputation: 138
I'm quite new to the superheroic framework AngularJS, so please excuse my noobness! So, while I was trying to develop a simple SPA that allowed admins to change permissions of other users in my website through a table filled with selection checkboxes, I came by an issue. I defined $scope.checked
so I could know how many users the administrator chose and also $scope.mainCheckBox
which would hold the correct CSS class for the major checkbox (like the one from Gmail, which you use to select all/none) in each of the three situations: all users selected, no users selected and partial selection. This simple logic goes as follows:
$scope.updateMainCheckBox = function(){
if(this.checked==this.users.length) this.mainCheckBox = "qm-icon-checked";
else if(!this.checked) this.mainCheckBox = "";
else this.mainCheckBox = "qm-icon-minus";
};
Running this at the end of the ng-click event callback of the other checkboxes, this code was capable of choosing the class correctly but it wouldn't assign the class to the mainCheckBox
. When I changed every this.mainCheckBox
to $scope.mainCheckBox
it all went well and the page would behave as expected.
So, I know in vanilla Js this
is a reference to the window
object but since AngularJS has its own event handling loop, I believe that's not the case now. I expected it to be a ref to $scope
, since checked
and users
were found, but apparently it's not. So, what's happening here? And also, is there a more "angular" way to implement this?
Upvotes: 1
Views: 443
Reputation: 159135
You're mostly right--in the case of your function, this
did reference a scope. But, it did not reference $scope
; instead, it referenced one of $scope
's children.
Try this: add some console.log
statements to log out the ID of the $scope
variable, and then the ID of the this
scope in your callback:
$scope.updateMainCheckBox = function(){
console.log('$scope:', $scope.$id);
console.log('this:', this.$id);
// ...
};
You'll find the IDs are different. This is because the ngRepeat
directive creates a child scope, which is a scope that inherits prototypally from its parent. This means that when you assign directly to a value on that scope, it's not reaching the parent scope, which is $scope
.
I highly recommend a read through the excellent (and lengthy) "The Nuances of Scope Prototypal Inheritance" by Mark Rajcok; it esplains why you see this seemingly strange behavior on child scopes. (You can also find a copy on the AngularJS wiki.)
Upvotes: 2