Learn how to use the exact same HTML, yet let Angular bind that markup to different pieces of data.

In Part I of this series: “Getting Started With Angular.js: Data-Binding Basics With the ng-model Directive (Part I),” we covered the absolute basics of data-binding with Angular.js. In that article, we discussed how multiple elements can be bound to the same piece of data, and when that data changes, any elements bound to it are updated.

While this kind of abstraction is incredibly useful and powerful, it is a simple scenario. Having multiple DOM elements that are bound to different pieces of data is probably a more real-world context for a front-end web developer.

In this article, we will learn how to use the exact same piece of HTML yet let Angular bind that markup to different pieces of data.

Example # 1

In Example # 1, we have some very simple HTML. There is an input element, and a paragraph. You will probably notice that this HTML looks a bit unusual. The input element has what looks like an HTML attribute named: “ng-model”. But this is not a standard HTML attribute, it is actually an Angular directive. It specifies the data that this element will be bound to.

The second area where you may notice something unusual is the text: {{myData}} that is inside of the SPAN element with the class: “val”. This functions as a placeholder for some data that is named: “myData”.

The HTML detailed above will be used numerous times in this article’s examples. The main point to stress here, is that this HTML is generic in nature; there are no HTML ID attributes in use, and no data is hard-coded. For this reason, it can be used more than once, exactly as-is, throughout our HTML.

Example # 2

In Example # 2, we have two “child” elements. These simply serve as containers for the code in Example # 1. These elements are almost completely generic. The only thing that differentiates them from each other is the Angular directive: “ng-controller”. They each reference a different controller. There is a reason for this, which will be addressed shortly. Other than the value of the “ng-controller” directive, the HTML of these two elements is identical.

NOTE: If you look at the BODY tag, you will see that this element also has an Angular directive: ng-app (<body ng-app>). This tells Angular that it should manage all elements contained inside of that element.

Example # 3

In Example # 3, we have two functions: “leftController” and “rightController”. You may recognize the names from the two Angular directives mentioned in Example # 2. Controllers allow you to provide private variable scope on a per-element basis. Each element in your application that has an “ng-controller” directive has its own $scope object, which is a variable in a function behind the scenes, which makes it private. Each instance of this object can be extended as-needed. Even though the two functions specified in Example # 3 do absolutely nothing at this point, they are required because the “ng-controller” directive tells Angular: “hey, use this function for this element, in order for it to have its own private $scope object.” So, even if it does nothing, the function must exist globally.

Note: it is highly recommended that you leverage best practices such as name-spacing in order to make your controllers accessible while keeping the global name-space clutter-free. This kind of design pattern is out of the scope of this article, but you can learn more about it in my article: “Using an Immediate Function to Create a Global JavaScript Variable That Has Private Scope.”

Example # 4

In Example # 4, we have placed the HTML from Example # 3 inside of a “child” element. This means that the data referenced by: “myData” is private to the element: div.child.left. When you look at the working code for this example, you’ll see that anything you type in the input field is injected into the DOM.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 4: http://fiddle.jshell.net/Pnwz4/

How to Demo: Type anything in the text box. You’ll see that whatever you type is updated in the element below the text box. Both the text-box and the element that displays the text are bound to the “myData” property of the same object, which has been created by Angular. This object is a private variable, created by the controller: “leftController”.

Example # 5

In Example # 5, we have added a second copy of the input element HTML. Because they both reside within the element with the Angular directive: ng-controller=”leftController”, all references to “myData” point to the same object’s “myData” property.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 5: http://fiddle.jshell.net/Pnwz4/1/

How to Demo: Type anything in either text box. You’ll see that anything you type in either input field is injected into the DOM. Once again, this is because all references to myData point to the same object.

Example # 6

In Example # 6, we have moved the second INPUT element (and associated elements) to a different “child” element, which has its own ng-controller directive. This means that although each INPUT element and client side template references data named: “myData”, they are referencing different data (in each case, “myData” is a property of the $scope object that is a private variable of a different function).

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 6: http://fiddle.jshell.net/Pnwz4/2/

How to Demo: Type anything in either text box. You’ll see that only the DOM element that resides in the associated “child” element is updated. This is because each “child” element references a different ng-controller directive, which provides a privately-scoped variable containing the object that holds the “myData” value.

Example # 7:

In Example # 7, we have the complete HTML for this article’s working example. When you type in the text-input of each child element, the text you type is injected into the DOM.

Summary

The purpose of this article was to demonstrate how the exact same HTML can easily be used in more than one place, but access completely different data by leveraging Agular.js. We were able to accomplish this by creating two different container (aka “child”) elements that had different ng-controller directives. Because each Angular controller creates its own privately-scoped $scope object, two pieces of HTML that are both bound to the same-named data actually reference completely different data. While the examples in this article were extremely simple, I hope they provided a way for you to gain a basic understanding of how Angular controllers provide private data scopes for HTML elements with minimal effort on the part of the developer.

The most important concepts discussed here are:

  • Angular.js directives are extensions of HTML, and look / function much like attributes.
  • The ng-controller directive provides a privately-scoped $scope object for an element.
  • When you specify an ng-controller directive for an element, you must be sure to make a function available that matches the value of the ng-controller directive (this can be a function declaration or a function expression).

Helpful Links for the Angular.js $scope object

http://docs.angularjs.org/api/ng.$rootScope.Scope

http://www.ng-newsletter.com/posts/beginner2expert-scopes.html

http://docs.angularjs.org/guide/directive

http://blog.kevinchisholm.com/angular/angular-js-data-binding-basics-the-ng-model-directive-part-i/

One Comment

Comments are closed.