Getting Started With AngularJS – Scope

In this blog post we will see in more detail about angular $scope variable

We use $scope to bind data between angular and DOM. $scope is injected to a controller using Dependency Injection.

$scope is local to each controller, i.e it is not shared between controllers.

$rootScope

$rootScope is the top level scope object and all other scopes created are child to this scope. These is only a single $rootScope in a single angular application. Lets see a working example of $rootScope and how its shared between 2 controllers.

  
var mainMod = angular.module('MainApp', []);
  
mainMod.controller('MainCtrl', ['$scope','$rootScope',
      
function ($scope,$rootScope) {
        
$scope.update = function(){
          
$rootScope.text2 = $scope.text1;
        
}
      
}
  
]);

mainMod.controller('MainCtrl2', ['$scope','$rootScope',
      
function ($scope,$rootScope) {
        
$scope.update = function(){
          
$rootScope.text1 = $scope.text2;
        
}
      
}
  
]);
  

Our HTML code

  
<body ng-app='MainApp'>
      
<div ng-controller='MainCtrl'>
        
<div>
          
<div>Controller1</div>
          
<input type='text' ng-model='text1'/>
          
<button type='button' ng-click='update();'>Update</button>
        
</div>
      
</div>
      
<div ng-controller='MainCtrl2&#8242;>
        
<div>
          
<div>Controller2</div>
          
<input type='text' ng-model='text2'/>
          
<button type='button' ng-click='update();'>Update</button>
        
</div>
      
</div>
  
</body>
  

In the above example, if type text in first controller and press ‘Update’ button it gets reflected to the second controller as well. Using this we see that $rootScope is common and shared between all controllers.

More details here

$watch

$scope and $rootScope provide a $watch function. $watch function is used to listen for any changes in $scope variables. More details here Lets extend the above example and see its working

  
var mainMod = angular.module('MainApp', []);
  
mainMod.controller('MainCtrl', ['$scope','$rootScope',
      
function ($scope,$rootScope) {
        
$scope.$watch('text1',function(newValue,oldValue){
          
if(newValue){
            
$rootScope.text2 = newValue;
          
}
        
});
      
}
  
]);

mainMod.controller('MainCtrl2', ['$scope','$rootScope',
      
function ($scope,$rootScope) {
        
$scope.$watch('text2&#8242;,function(value){
          
if(value){
              
$rootScope.text1 = value;
          
}
        
});
      
}
  
]);
  
  
<body ng-app='MainApp'>
      
<div ng-controller='MainCtrl'>
        
<div>
          
<div>Controller1</div>
          
<input type='text' ng-model='text1'/>
        
</div>
      
</div>
      
<div ng-controller='MainCtrl2&#8242;>
        
<div>
          
<div>Controller2</div>
          
<input type='text' ng-model='text2'/>
        
</div>
      
</div>
  
</body>
  

Now if you type in Controller1, Controller2 get automatically updated. This is because using $watch we keep on updating the $rootScope.

$apply

There might be many instances, when value of a scope variable might change outside of angular scope. e.g browser dom events, jquery document ready event, setTimeout, 3rd party libraries or any other such external factors. To sync the $scope back we use $apply function. Lets demonstrate this using an example

  
var mainMod = angular.module('MainApp', []);
  
mainMod.controller('MainCtrl', ['$scope','$rootScope',
      
function ($scope,$rootScope) {
        
$scope.update = function(){
          
setTimeout(function(){
            
$scope.text1 = 'New Text';
            
$scope.$apply(); //removing this New Text won't be updated
          
},500);
        
}
      
}
  
]);
  
  
<body ng-app='MainApp'>
      
<div ng-controller='MainCtrl'>
        
<div>
          
<div>Controller1</div>
          
<input type='text' ng-model='text1'/>
          
<br/>
          
Text: {{text1}}
          
<br/>
          
<input type='button' ng-click='update();' value='Update Outside' />
        
</div>
      
</div>
  
</body>
  

In the above example, setTimeout is used simulate an event which is outside angular $scope. If in the above example we remove $scope.$apply() the text is not updated.

More details here

$scope Events $on,$emit,$broadcast

$scope and $rootScope object exposes many events which we can use to transmit data.

$on: This is used to listen to any event fired.

  
$scope.$on('test_event',function(event){
  
});
  

$emit: This is used to fire an event to all its parent scopes, till the $rootScope

  
$scope.$emit('test_event');
  

$broadcast: This is used to fire an event to all its child scopes.

  
$scope.$broadcast('test_event');
  

Let see an example to see how these work.

  
var mainMod = angular.module('MainApp', []);
  
mainMod.controller('MainCtrl', ['$scope',
      
function ($scope) {
        
$scope.name = 'Ctrl1&#8242;;
        
$scope.update = function(){
          
$scope.$emit('emit_event');
        
}
        
$scope.update2 = function(){
          
$scope.$broadcast('broadcast_event');
        
}
        
$scope.$on('emit_event',function(event){
           
$scope.event = 'emit event from ' + event.targetScope.name
       
})
       
$scope.$on('broadcast_event',function(event){
           
$scope.event = 'broadcast event from ' + event.targetScope.name
       
})
      
}
  
]);
  
mainMod.controller('ChildCtrl',function($scope){
        
$scope.name = 'Ctrl2&#8242;;
        
$scope.update = function(){
          
$scope.$emit('emit_event');
        
}
        
$scope.update2 = function(){
          
$scope.$broadcast('broadcast_event');
        
}
       
$scope.$on('emit_event',function(event){
           
$scope.event = 'emit event from ' + event.targetScope.name
       
})
       
$scope.$on('broadcast_event',function(event){
           
$scope.event = 'broadcast event from ' + event.targetScope.name
       
})
  
});
  
  
<body ng-app='MainApp'>
      
<div ng-controller='MainCtrl'>
        
<div>
          
<div>Controller1</div>
          
Event: {{event}}
          
<br/>
          
<input type='button' ng-click='update();' value='Emit Event' />
          
<input type='button' ng-click='update2();' value='Broadcast Event' />
          
<br/>
           
<div ng-controller='ChildCtrl'>
             
<div>Child Controller</div>
             
Event: {{event}}
             
<br/>
             
<input type='button' ng-click='update();' value='Emit Event' />
             
<input type='button' ng-click='update2();' value='Broadcase Event' />
          
</div>
        
</div>
      
</div>
  
</body>
  

In the above example, we create 2 controllers one controller is child of another. $scope also becomes child of another and we can clearly see difference between $emit and $broadcast.

All these event functions are also available on $rootScope as well.

$rootScope $emit/$broadcast

As we saw above $emit is used to send data upwards and $broadcast is used to send data downwards. So in $rootScope, $emit won’t make any sense since there is no parent to $rootScope. But there is a small difference in $rootScope.$emit, it only send events to $rootScope.$on listeners. If you used $rootScope.$broadcast, it send event to all listeners ($rootScope.$on and $scope.$on)

We can see more detailed explanation about Scopes here

excellence-social-linkdin
excellence-social-facebook
excellence-social-instagram
excellence-social-skype