A great feature of scopes is that they are organized in a hierarchy. The hierarchy helps you keep scopes organized and relevant to the context of the view they represent. There is a root scope at the AngularJS module level and then child scopes can be implemented in sub-components such as controllers or directives. Child scopes can be nested within each other creating a hierarchy structure.
Note
The $digest()
method uses the scope hierarchy to propagate scope changes to the appropriate watchers and the DOM elements.
Scope hierarchies are created automatically based on the location of ng-controller
statements in the AngularJS template. For example, the following template code defines two <div>
elements that create instances of controllers that are siblings:
<div ng-controller="controllerA"> . . . </div>
<div ng-controller="controllerB"> . . . </div>
However, the following template code defines controllers in which controllerA
is the parent of controllerB
:
<div ng-controller="controllerA">
<div ng-controller="controllerB"> . . . </div>
</div>
The scope hierarchy works similar to the way object inheritance works in OO languages. You can access the values of parent scopes from a controller, but you can’t access the values of sibling or children scopes. If you add a property name in a child scope, it does not overwrite the parent but creates a property of the same name in the child scope that has a different value from the parent.
Listings 4.5 and 4.6 implement a basic scope hierarchy to demonstrate how scopes work in a hierarchy. Listing 4.5 creates an application with three controllers, each with two scope items defined. They all share the common scope property title
and the scope properties valueA
, valueB
, and valueC
.
Listing 4.6 creates the three controllers in an AngularJS template. Figure 4.3 shows the rendered AngularJS application. Notice that the value of the title
property in all three scopes is different. That is because a new title
property is created for each level in the hierarchy.
Lines 17–19 display the valueA
, valueB
, and valueC
properties. These values are read from three different levels in the scope hierarchy. The application shows that as you increment the value in the parent scope, a DOM element in a child controller is updated with the new value.
01 angular.module('myApp', []).
02 controller('LevelA', function($scope) {
03 $scope.title = "Level A"
04 $scope.valueA = 1;
05 $scope.inc = function() {
06 $scope.valueA++;
07 };
08 }).
09 controller('LevelB', function($scope) {
10 $scope.title = "Level B"
11 $scope.valueB = 1;
12 $scope.inc = function() {
13 $scope.valueB++;
14 };
15 }).
16 controller('LevelC', function($scope) {
17 $scope.title = "Level C"
18 $scope.valueC = 1;
19 $scope.inc = function() {
20 $scope.valueC++;
21 };
22 });
01 <!doctype html>
02 <html ng-app="myApp">
03 <head>
04 <title>AngularJS Scope Hierarchy</title>
05 </head>
06 <body>
07 <div ng-controller="LevelA">
08 <h3>{{title}}</h3>
09 ValueA = {{valueA}} <input type="button" ng-click="inc()" value="+" />
10 <div ng-controller="LevelB"><hr>
11 <h3>{{title}}</h3>
12 ValueA = {{valueA}}<br>
13 ValueB = {{valueB}}
14 <input type="button" ng-click="inc()" value="+" />
15 <div ng-controller="LevelC"><hr>
16 <h3>{{title}}</h3>
17 ValueA = {{valueA}}<br>
18 ValueB = {{valueB}}<br>
19 ValueC = {{valueC}}
20 <input type="button" ng-click="inc()" value="+" />
21 </div>
22 </div>
23 </div>
24 <script src="http://code.angularjs.org/1.3.0/angular.min.js"></script>
25 <script src="js/scope_hierarchy.js"></script>
26 </body>
27 </html>