AngularJS Nested Scopes And Controllers As Syntax

Overview

In this article we will cover the following

  • AngularJS "Nested Scopes" and "Controllers as Syntax"
  • Controller vs Scope

For more articles on AngularJS, please refer these links.

First, let's look into "Nested Scopes" and "Controllers as Syntax".
 
Introduction

"Controllers as Syntax" can make our code more readable while working with "Nested Scopes". For this, we need to have an idea of Controllers as Syntax, given ahead in this article.

Here, we will make a Country Controller, State Controller, and City Controller respectively in our script file. I have created an empty website and in that, I created a Scripts folder and added the AngularJS script files.

Now, add a JavaScript file and name it as script.js. Reference the angular.min.js as shown below.
  1. /// <reference path="angular.min.js" />  
Now, add these lines in the Controller.
  1. var app = angular.module("Demo", [])  
  2.                    .controller("CountryController"function ($scope) {  
  3.                        $scope.name = "India";  
  4.                    })  
  5.                       .controller("StateController"function ($scope) {  
  6.                           $scope.name = "Maharashtra";  
  7.                       })  
  8.                       .controller("CityController"function ($scope) {  
  9.                           $scope.name = "Mumbai";  
  10.                       })  
As you can notice that we have created a Module named as Demo and passed three Controllers as Country Controller,State Controller and City Controller respectively. Notice that we have used $scope object to pass those Controllers and in all those three Controllers, we are using .name commonly.

Now, we will create a simple HTML page and in that, we will reference AngularJS script file along with our script file. Then, we will include three div elements to display those details .
  1. <html>  
  2. <head>  
  3.     <title></title>  
  4.     <meta charset="utf-8" />  
  5.     <script src="scripts/angular.min.js"></script>  
  6.     <script src="scripts/script.js"></script>  
  7. </head>  
  8. <body>  
  9. <div>  
  10.     <div>  
  11.   
  12.     </div>  
  13.     <div>  
  14.   
  15.     </div>  
  16. </div>  
  17. </body>  
  18. </html>  
Initialize with ng-app and ng-controller in your HTMl file. As you can see, we have used nested divs and the Controller name respectively, because we want to display the Country Controller first. Then, State Controller and then City Controller. We bind these with the names as we will use binding expression. So, our View will be as,
  1. <!DOCTYPE html>  
  2. <html ng-app="Demo">  
  3. <head>  
  4.     <title></title>  
  5.     <meta charset="utf-8" />  
  6.     <script src="scripts/angular.min.js"></script>  
  7.     <script src="scripts/script.js"></script>  
  8. </head>  
  9. <body>  
  10. <div ng-controller="CountryController">  
  11.     {{name}}  
  12.     <div ng-controller="StateController">  
  13.         {{name}}  
  14.         <div ng-controller="CityController">  
  15.             {{name}}  
  16.         </div>  
  17.     </div>  
  18. </div>  
  19. </body>  
  20. </html>  
Let's save the changes and run the application. We see the following.

output

We have got various respective Controllers but when we see our View Code, its quite confusing because these three Controllers are nested inside each other and we have a common name property.

Since we have developed this View, we are aware of the common name property but for others, it is more confusing.

Now, we will be seeing how to display $parent Controller inside the State Controller. We will pass this $controller to the State Controller and see how much more confusing the code can be. So, let's go back to our HTML page. Locate the following code.
  1. <div ng-controller="StateController">  
  2. {{$parent.name}} - {{name}}  
Let's reload the page and check the output.

output

Now, suppose I want a grand parent name in our City Controller, then we will write the following code.
  1. <div ng-controller="CountryController">  
  2.     {{name}}  
  3.     <div ng-controller="StateController">  
  4.         {{$parent.name}} - {{name}}  
  5.         <div ng-controller="CityController">  
  6.             {{$parent.$parent.name}} -    {{$parent.name}} -  {{name}}  
  7.         </div>  
  8.     </div>  
  9. </div>  
I have used here $parent.$parent.name in the City Controller. Let's save the changes and reload the page. We get the following screen.

output

Now, we have only three levels of Controller here. Imagine, if there are 20 levels of Controller Nest, how deep will it be. This will add more confusion. To avoid these and as a good programming practice, we will use "Controller as Syntax". To use "Controller as Syntax" in your script file, get rid of the $scope object and use this keyword. So, let's implement that first.
  1. /// <reference path="angular.min.js" />  
  2. var app = angular.module("Demo", [])  
  3.                    .controller("CountryController"function () {  
  4.                        this.name = "India";  
  5.                    })  
  6.                       .controller("StateController"function () {  
  7.                           this.name = "Maharashtra";  
  8.                       })  
  9.                       .controller("CityController"function () {  
  10.                           this.name = "Mumbai";  
  11.                       })  
Now, in our View, we will use Controller as Syntax.
  1. <div ng-controller="CountryController as CountryCtrl">  
  2.     {{name}}  
  3.     <div ng-controller="StateController as StateCtrl">  
  4.         {{$parent.name}} - {{name}}  
  5.         <div ng-controller="CityController as CityCtrl ">  
  6.             {{$parent.$parent.name}} -    {{$parent.name}} -  {{name}}  
  7.         </div>  
  8.     </div>  
  9. </div>  
Now, to access the Country Controller, we will use CountryCtrl.name. Similarly, we will use StateCtrl.name for state and CityCtrl.name for City.
  1. <div ng-controller="CountryController as CountryCtrl">  
  2.     {{CountryCtrl.name}}  
  3.     <div ng-controller="StateController as StateCtrl">  
  4.         {{CountryCtrl.name}} - {{StateCtrl.name}}  
  5.         <div ng-controller="CityController as CityCtrl ">  
  6.             {{CountryCtrl.name}} -    {{StateCtrl.name}} -  {{CityCtrl.name}}  
  7.         </div>  
  8.     </div>  
  9. </div>  
Now, when you see the code, its more readable and makes better sense. So, what is CountryCtrl here? It is the instance of the Country Controller. 

Now, let's save the changes and reload the page. We get the following output.

output

Now, let's see the difference in $scope and "Controller as Syntax".

"Controller as Syntax" is new and it's officially released in 1.2 and above versions. $scope is an old technique that is available since initial versions of AngularJS. You can use either of the two. But, Controller as Syntax makes your code more readable as we have seen earlier in Nested Scopes.

If you want to use $scope, it has to be injected into Controller function. Whereas, for Controller as Syntax, you don’t have a need to inject into Controller function.

NOTE: When you are using Controller as Syntax, don’t be under impression that Angular is not using $scope. Actually, behind Controller as Syntax, it is using $scope. It's just hiding that .

Let's see an example of this.
  1. <div ng-controller="CountryController as CountryCtrl">  
  2.     {{CountryCtrl.name}}  
  3.     <div ng-controller="StateController as StateCtrl">  
  4.         {{CountryCtrl.name}} - {{StateCtrl.name}}  
  5.         <div ng-controller="CityController as CityCtrl ">  
  6.             {{CountryCtrl.name}} -    {{StateCtrl.name}} -  {{CityCtrl.name}}  
  7.         </div>  
  8.     </div>  
  9. </div>  
Here, we are using Controller as Syntax in our City Controller as CityCtrl. So, this is a reference variable pointing to the instance of the CityControllers and Angular is actually taking that reference and attaching that to the $scope object . Now suppose, you have the name property that you use in CityCtrl.name. The City Controller is actually attached to the $scope object but it's just hidden.

Conclusion

So, this was all about AngularJS Nested Scopes and Controllers, and difference between $scope and Controller as Syntax . Hope this article was helpful.