Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!
28 Oct 2016

Angularjs Tutorial: Understanding Scope

angularjs

This is the second part of Learning Angular, please make sure you have read the first part Basics

We will start with a basic seed project, you can download the seed project here. The seed project has the necessary dependency of js file, so you do not have to download different js files from various sources.

Once we have added the angular js to our project, we need to tell angular which part of DOM we want angular to manage, in most of the cases it would entire DOM but it is possible to have angular managed and non angular managed code in same application.

Bootstrapping Angular

There are two ways to initialise angular, the most popular way is using ng-app on the DOM which we want angular to manage.

<body ng-app="myApp">

app.js

 var app = angular.module('myApp', []);

This would tell angular that we have a module called myApp somewhere in the code.

The other way of initializing angular is through javascript.

 var app = angular.module('myApp', []);
 angular.bootstrap(document,['myApp']);

In most of the cases, you would use the first approach, but in some cases like if you using requireJs then you would need to use later approach.

Controller

As we had discussed in last part we would need to define a controller to handle the $scope for the DOM. Typically we would have multiple controllers handling various part of DOM. A general guideline you can use is that if you can think of a DOM like a widget, create a new controller for it.

In our little hello world example we would have one controller for entire application. Lets add following code to our app.js

app.controller('testController',function($scope){
 $scope.firstName = 'John';
 $scope.lastName = 'Doe';
});
<body ng-app="myApp" ng-controller="testController">
Hello {{firstName}} {{lastName}}

Now lets try to run our code. While you can try to open the file in a browser and see this code running, it is a good idea to run the application through a server, this allows us to use Ajax which would not work without a server. However we would not want to create some heavy weight server just to test our angular application. For this we would use http-server to simply serve our static content, for this you would need to install npm, once you have npm run following command.

npm install http-server

Once installed you can run

http-server

this would run a static server on port 8080, now you can go to http://localhost:8080 to see your code running.

Scope

Lets try to dig a bit deeper and understand what is happening here, so we would open the console tool in chrome and select body tag in html, then go to console and type

$($0).scope()

Essentially $0 is alway the last selected item in chrome dev tool, I find that very useful. You can try and use $1, $2 and so forth..

This is how your scope should look like.

Scope

if you see the firstName and lastName is set to appropriate values. If you notice each scope has an id, in this case the id is 2, and it also has a $parent attribute, if you open the $parent the id should be 1, also there is a property called _proto_ , if you want to know more what this property is, read Understanding Prototype

So essentially each $scope is prototype inherited from parent $scope and each $scope has a reference to $root which is the rootScope and parent of all the $scope. If you type

$($0).scope().$root.$id

it should print 1 which is also the parent of our controller scope as we saw.

Now let try to do something funky.. :)

We would try to change the scope variable from chrome console and see if that changed the view. Lets try to type following in console and see.

$($0).scope().firstName = 'Jane'

The view did not change, right? So what happened ? Since we modified the scope variable outside angular managed code, angular still does not know that the variables have changed. So we would need to tell angular that variables have changed and we would do this by calling $scope.$digest() so lets change the above code to

$($0).scope().firstName = 'Jane'
$($0).scope().$digest();

And voila! our view changed.

Directive Scope

Lets try to add a list of names to our page using ng-repeat. Lets add a list of names of our controller.

 $scope.items = [
        {name:'Eddard Stark'},
        {name:'Robb Stark'},
        {name:'Sansa Stark'},
        {name:'Arya Stark'},
        {name:'Brandon Stark'},
        {name:'Rickon Stark'},
        {name:'John Snow'}

    ];
<ul>
    <li ng-repeat="i in items">{{i.name}}</li>
</ul>

If you are not a Game Of Thrones fan, you can assume they are just some random names. Now the ui should render a list of names as given below, lets check the scope again, this time we would pick the li elements and check the scope variable applied to them.

<ul>
    <!-- ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">Eddard Stark</li>
    <li ng-repeat="i in items" class="ng-binding ng-scope">Robb Stark</li>
    <!-- end ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">Sansa Stark</li>
    <!-- end ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">Arya Stark</li>
    <!-- end ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">Brandon Stark</li>
    <!-- end ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">Rickon Stark</li>
    <!-- end ngRepeat: i in items -->
    <li ng-repeat="i in items" class="ng-binding ng-scope">John Snow</li>
    <!-- end ngRepeat: i in items -->
</ul>

If you see now the scope should have changed.

angular scope

This is the scope of second li child which has an id 11 and has the parent as id 2 which was our original controller scope. Not only that, every li should have a different scope each extending from our controller scope.

This is because we used the directive ng-repeat, each instance of directive gets assigned a new scope which extends from the current directive scope. So our scope id 2 is essentially a scope assigned to the ng-controller directive and each of ng-repeat as shown in the html above gets a new scope derived from parent scope.

I hope this should settle the debate on how scope as assigned to directives and controllers. In next part we would create a custom directive and look at how scope isolation works with directives and child controllers.

Keep Calm and Keep Coding


Stats:
570 views
Scaffold your ideas into application
Get your free alpha access now.
Only 445 left, Hurry!

Angular Directives Demystified

Directives are the most misunderstood aspect of angular JS. Learn how directives can help you keep your code clean.

Third wave of digital transformation

Third wave of digital transformation

Angularjs Tutorial: Basics

This article covers the basic fundamental concept of Angular JS

Comments:

Leave your comments