Reputation: 831
I am new to angularjs and got a confusing thing which I thought is probably an anomaly in controller hierarchy in accessing parent scope. Below are the two code snippets, I think both must work according to the principle of accessing parent scope but...
1) This one is working:
<body data-ng-app>
<div data-ng-controller="ctrl1">
Greeted : {{first.greeted}}
<div data-ng-controller="ctrl2">
<a href="#" data-ng-click="sayClick()">Click To Greet</a>
</div>
</div>
<script>
function ctrl1($scope){
$scope.first = {greeted: "No"};
}
function ctrl2($scope){
$scope.sayClick= function(){
$scope.first.greeted = "Yes";
}
}
</script>
</body>
2) and this one is not:
<body data-ng-app>
<div data-ng-controller="ctrl1">
Greeted : {{first}}
<div data-ng-controller="ctrl2">
<a href="#" data-ng-click="sayClick()">Click To Greet</a>
</div>
</div>
<script>
function ctrl1($scope){
$scope.first = "No";
}
function ctrl2($scope){
$scope.sayClick= function(){
$scope.first = "Yes";
}
}
</script>
</body>
Could someone please tell me whats the difference between the two and why second one isn't working?
Upvotes: 1
Views: 405
Reputation: 55
In the first case, you are dealing with objects and in the 2nd case with direct primitive values on the scope.
a) each controller creates it own scope; b) angular goes up the scope hierarchy until it finds the OBJECT its looking for, but c) if instead of being an object its a value, it creates the PRIMITIVE value in the current controller's scope, overwriting and value it previously inherited from a parent scope.
To avoid this confusion, use objects all the time. Instead of $scope.A and $scope.B, create something like $scope.data = {} and then assign $scope.data.A and $scope.data.B
Then in your view, you refer to data.A and data.B The nested controller will go up the hierarchy until it finds the data object instead of creating a new one.
Upvotes: 1
Reputation: 193301
In angular scope inheritance is implemented using standard Javascript prototype inheritance. The difference between two examples is that in the second one you deal with primitive values which can't be inherited the way you think. When you do
$scope.first = "Yes";
in the second controller it simply creates new scope property which "shadows" parent scope property. However in the first example first.greeted
is a object reference to parent scope object first
, and since it's not primitive, it preserves object reference.
To illustrate the issue with pure Javascript objects (the same happens in your Angular code), consider this little example.
var obj1 = {
profile: { // object
id: 1
},
name: 'Obj1' // primitive
};
// create obj2 with obj1 set as its prototype
var obj2 = Object.create(obj1);
// Change promitive and object referenced property
obj2.name = 'Obj2';
obj2.profile.id = 2;
document.body.innerHTML = obj1.name + ', ' + obj2.name;
document.body.innerHTML += '<br>' + obj1.profile.id + ', ' + obj2.profile.id;
To avoid confusion it's often recommended to use object references, which is known as "dot-rule".
Upvotes: 1