Introduction To Scope In AngularJS

Scope

Scope is a JavaScript object that plays the role of the binding part between the View and the Controller. Scope contains the model data. Model data is accessed via $scope in Controllers. Scope is available for both View and Controller.

We pass $scope object as an argument whenever we make a Controller. $scope is passed as first argument to the constructor of the Controller. We can define functions in $scope also.

$scope provides APIs to propagate any Model changes into the View from outside of the Controllers, Services, or event handlers. We can even make child scopes and isolate scopes. Child scope inherits properties from its parent scope while an isolated scope doesn’t. Scopes can watch expressions and propagate events. Properties that are made in Controller can be referred to in the View.

Let’s understand this with an example.

First of all, we will create a Controller and pass $scope object as an argument to the Controller constructor.

  1. var app = angular.module('myApp', []);  
  2. app.controller('myController'function($scope) {  
  3.     $scope.myMessage = "From Scope";  
  4. });   
Here, we have passed $scope as an argument and added a property named as myMessage to it with some value. Now, we can view this value in View by using expression and initializing this Controller in which this scope object is passed.

View
  1. <div ng-app="myApp" ng-controller="myController">  
  2.     <h1>{{myMessage}}</h1>  
  3. </div> 

The value of $scope.myMessage will be reflected here in the expression {{myMessage}}, because in this Controller's scope, the value of this myMessage is assigned as “From Scope”. If we run this, we will get the same output.

Output

When we add properties to the $scope object in the Controller, View gets the access to these properties. We just refer to property name in the View to access the property of the scope.

Inheritance in scope

Scopes are specific to Controllers they are injected in. In nested Controllers, child controllers inherit the scope of the parent controller. Each Angular application has exactly one root scope but may have several child scopes.

Let’s understand this with an example.

Inheritence.js

  1. var mainApp = angular.module("myApp", []);    
  2.     
  3. mainApp.controller("myController"function ($scope) {    
  4.     $scope.myMessage = "first controller";    
  5. });    
  6.     
  7. mainApp.controller("newController"function ($scope) {    
  8.     $scope.myMessage = "new controller";    
  9. });   
View
  1. <!DOCTYPE html>    
  2. <html xmlns="http://www.w3.org/1999/xhtml">    
  3. <head>    
  4.     <title>Angular Scope By Jasbeer Singh</title>    
  5.     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>    
  6.     <script src="inheritence.js"></script>    
  7. </head>    
  8. <body>    
  9.     <div ng-app="myApp" ng-controller="myController">    
  10.     
  11.         <h1>{{myMessage}}</h1>    
  12.     
  13.         <div ng-app="myApp" ng-controller="newController">    
  14.     
  15.             <h1>{{myMessage}}</h1>    
  16.     
  17.         </div>    
  18.     
  19.     </div>    
  20.     
  21.     <!--<script>    
  22.         var app = angular.module('myApp', []);    
  23.     
  24.         app.controller('myController'function ($scope) {    
  25.             $scope.myMessage = "From Scope";    
  26.         });    
  27.     </script>-->    
  28. </body>    
  29. </html>   
You can see in the above example that we have overridden the value of myMessage in newController. When newController is initialized, it will override the myMessage value. If we run this, we will get the output like the following.

Root Scope

All applications have a root scope that is created on the HTML element that contains ng-app directive. This root scope is available in the entire application. This is denoted as $rootScope. All other scopes are descendants of the root scope.

Scope Life cycle

Angular is unaware of model modifications. The whole execution has to go through the Angular execution context using the method called $apply. Only model modifications that occur or execute inside the $apply method are properly accounted for by Angular. Let's see an example of ng-show.

For ng-show, if the directive listens this DOM event, it must evaluate the expression inside the $apply method. After evaluating the expression, the $apply method performs $digest phase. In $digest phase, Angular examines all the $watch expressions and compares them with the previous values. Then, asynchronously dirty checking takes place which scans the scope for changes.
 
Dirty checking is the process of checking every $watch to detect the changes. $watch is not immediately notified by Angular about the assignment of properties to $scope but is delayed until the $digest phase. It guarantees that during $watch notification, no other $watch is running. If value is changed by a $watch, then it forces additional $digest cycle.

Various steps are.

  1. Creation of root scope.
  2. Watchers are registered by directives on the scope.
  3. Scope.$apply() takes place for model mutation.
  4. After $apply(), $disgest() cycle takes place, this propagates through all child scopes. All $watched expressions are checked for model mutation and if any mutation /change is detected, then $watch listener is called.
  5. When child scopes are no longer needed, then scope.$destroy() is called to destroy scope.

Scopes are arranged in hierarchical order where $rootScope is at highest level, then child scopes come into play. Scope acts as linker between applications controller and view. Controllers and directives both have reference to scope but they (controller and view) cannot reference each other. Scopes are attached to DOM as $scope data property and can be retrieved for debugging purpose. Scopes can propagate events in similar fashion to DOM events. 

This article was about life cycle of scopes and use of scopes. After going through the article, please provide your valuable feedback.