Scope in AngularJS

AngularJS

One of the most important things in AngularJS is the scope. As you might be familiar with jQuery and Javascript, you know that this keyword can have different values in the same function called from different points in your application – one very clear example would be a delete row function for an already existing grid. Even though the same button(or whatever UI representation you chose) is the same, will delete only the specific row – unless there are bugs in code. Normally, the context will be set to the row, and the row element has the responsibility to provide a unique identifier for that specific record in your business logic. But AngularJS is a different beast, it uses context to partition your already big to huge application. And as with all Javascript frameworks, you will know if you made some mistakes only upon running code. So, although it seems pretty intuitive, I bet you don’t know exactly when, how and to which elements is applied. Am I right? Read the article and convince yourself.

Root scope

Let’s take a look at a minimal web application created with AngularJS:

<!DOCTYPE html>
<html ng-app="MyApp">
    <head>
        <title>My new App</title>
   <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
    </head>
<body>

</body>
</html>

As you can see, the code is plain HTML5.  The only used library is the latest AngularJS library (at writing time). After the page is loaded and the AngularJS script is executed, it searches for ng-app hook, which denote the root DOM element which will be used by module. What I love about it is that it is not strict to this, you may use data-ng-app (this is the correct HTML5 form for attributes – can be used if your website must be 100% compatible).The extra attribute in the tag represents the declaration of a module which will take care of instantiation and initialization of the rest of your code. Think of it as the main declaration of a jQuery script: $( ).ready(handler) only in simpler and more compact.

There is allowed only one application root per page, the first found during client-side parsing will be used; if one wants to have a page which is composed from multiple elements, bind multiple modules at desired element’s level or create custom directives (similar concept to partials in ASP .Net).

[ideabox]Note: By convention, AngularJS uses the dashed name for HTML attributes (a must if you want your website to be standard compliant) and camelCase for the implementation of the corresponding directives (standard casing in Javascript). So when you search for the implementation of ng-app tag, you actually search for ngApp.[/ideabox]

Controller scope

The controller scope is denoted by ng-controller tag which takes as argument the function of the ng-app module that will provide the JSON object used for databindings and callbacks for the buttons’ clicks, for example. But this will happen only in the scope of the controller’s associated root DOM element (including its children) and the scope of the ng-controller function. While one can go out by using simple jQuery searches of the parents of the corresponding root, it is not advisable. Later on, when I will write about unit testing, this will make much more sense; you will test a contained object and it’s inner interaction, instead of complex interactions between different controllers. Not to mention that you might get confused during maintenance of your project, not knowing exactly who modifies your context from outside. The bigger the application, the higher chances are that you’ll run into trouble!

<div ng-controller="OrderController">
	<h1>Your order</h1>
	<div ng-repeat="item in items">
		<span>{{item.product_name}}</span>
		<span>{{item.price | currency}}</span>
		<button ng-click="remove($index);">Remove</button>
	</div>
</div>

Repeater scope

In all application you’ll find at least one grid, a list representation of items which belong to common parent. For example, a list of items of your order you placed on a website. AngularJS provides a templated repeater which will automatically iterate through the collection of JSON objects that you provide as context. While on the root element of the repeater the context is the entire list, using a foreach paradigm, at individual rows, the corresponding element will be provided as its context. So, instead of having only the index and each time retrieve the item from collection, you have access at the specific item, providing you easier ways to create the HTML snippet in which properties of item will be injected:

So, here we have two context, one general at the list’s root and one specific for each item. This way you can work faster!

 

Leave a comment

Your email address will not be published. Required fields are marked *