Angular 1.x Data-Binding Basics: the ng-model Directive (Part III)

Angular

Although the Angular ng-model directive creates a privately-scoped object for an element, any descendants of that element also have access to that object.

In the previous article of this series: “Getting Started With Angular.js: Data-Binding Basics With the ng-model Directive (Part II)” we demonstrated how two HTML elements with their own unique ng-controller values can reference the same-named data value, yet access completely different data. The main purpose of that article was to demonstrate how each individual ng-controller directive creates a privately-scoped $scope object.

In this article, we will demonstrate how each privately-scoped $scope object inherits from the next ancestor with an ng-model directive, all the way up the DOM tree.

There are three very important native JavaScript concepts at play here:

  1. scope
  2. context
  3. object.prototype

Although a thorough discussion of any of these three topics is more than can adequately be covered here, it is important to note that they all come into play. I’ll point them where appropriate.

Example # 1

In Example # 1, we have an element with the class “parent”. It wraps the two “children” elements that we used in the previous article. Notice that the ng-model directive has a value of: “myData.parent”. This means that this element has a privately-scoped $scope object, with a property “myData”, which is an object, and that object has a property named “parent”. Note as well that the {{myData.parent}} placeholder is bound to the exact same data.

Example # 2

In Example # 2 we have a “child” element. Compared to the HTML from Part II of this article, there are a few changes:

The text box and span.val elements are bound to the data: “myData.left”
We have added two elements that are bound to “myData.parent”.

The reason for adding the second set of data-bound elements is to demonstrate that this “child” elements has access to not only its own privately-scoped data: “myData.left”, but also the “myData” property of the $scope object of it’s next descendant with an ng-model attribute. This is an example of leveraging JavaScript’s prototype object to create inheritance. While it may seem that JavaScript “scope” is driving this kind of parent -> child access to the Angular $scope object, it is, in fact, inheritance through the prototype object.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 2: http://jsfiddle.net/Gfm7Q/

How to Demo: Type anything in the box. You’ll see that when you type in the “parent” text box, both “children” have access to its data, and that updated data is injected into the DOM of each “child” element in real-time. Yet each “child” element has access to its own privately-scoped $scope.myData object (i.e. myData.left and myData.right).

Example # 3 A

Example # 3 B

In Example # 3A, we have a new element: “grandParent”. The exact same concept as the “parent” element applies: this element has an Angular ng-model directive with a value of: “myData.grandParent”, yet its privately-scoped $scope object is inherited by the “parent” object and both “child” objects.

In Example # 3B, we see a snippet of HTML that has been added to the “parent” and “child” elements. The purpose of this HTML is to demonstrate that we can bind DOM elements to data that belongs to ancestor elements.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 3: http://jsfiddle.net/Gfm7Q/1/

How to Demo: Type anything in the text box. You’ll see that when you type in the “Grand Parent” text-box, the “parent” element and both “children” have access to its data, and that updated data is injected into the DOM of each descendant element in real-time. The same goes for the “parent” element. Yet once again, each “child” element has access to its own privately-scoped $scope.myData object (i.e. myData.left and myData.right).

Example # 4

In Example # 4, we have the full HTML for this article’s working code.

Summary

Much like Part I and Part II of this series on Angular.js data-binding, the examples in this article are very simple. The goal was to provide a very basic demonstration of how DOM elements have access to the data that is bound to their ancestors via their ng-model directive. A key concept to focus on is the fact that Angular provides abstraction for this functionality which would require a great deal of code to replicate. Furthermore, this abstraction is application-agnostic, so you can leverage Angular for a wide range of projects. The features provided have no knowledge of how they will be employed. They “just work.”

Helpful Links for Angular $scope Inheritance

https://github.com/angular/angular.js/wiki/Understanding-Scopes

http://www.ramandv.com/blog/angular-js-sharing-data/

http://stackoverflow.com/questions/14232397/scope-inheritance-in-angularjs

http://www.cubicleman.com/2013/03/14/angularjs-and-a-js-prototypal-inheritance-gotcha/

Angular.js Data-Binding Basics: the ng-model Directive (Part II)

Angular

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/

Angular 1.x Data-Binding Basics: the ng-model Directive (Part I)

Angular

Grunt.js Logo
Data-binding with Angular.js is surprisingly simple. To get started, you need only specify an ng-model directive.

One of the most common tasks for any JavaScript developer is to inject a value into the DOM. This value can be a variable or the property of an object. When doing so, you need to make a reference to the target element, and then use a native JavaScript or jQuery method to inject that value (e.g. [SOME_ELEMENT].innerHTML or $(SOME_ELEMENT).html() ). But if that value is injected into more than one element, your work grows exponentially. You now have to manage multiple DOM element references, write code that makes the injections, and also code that pays attention to the data you are working with, so that when that data changes, you can update the DOM element(s) that need to know about that update.

Angular.js provides jaw-dropping abstraction that not only takes care of your messy DOM injection & data-management tasks, but does so with a simplicity and elegance that is truly to be admired.

This scenario can quickly spiral into a frustrating mess of nested-callbacks, hard-coded DOM element references and data-handling functions.

One of the main features of Angular is “Directives.” Angular.js directives are extensions of HTML. They look / function much like HTML attributes; each directive is part of the element’s opening HTML tag, and requires a value, which is enclosed in double-quotes. The ng-model directive specifies the name of a piece of data, which one or more elements can be bound to.

Before we get started, we’ll need to let Angular.js know that we want it to manage our web page. We can do this by adding an ng-app directive to the markup that we want managed (or an element on the page that is a descendant of that markup, such as HTML or BODY).

Example # 1

In Example # 1, we see the ng-app directive. This simply tells Angular to manage everything inside of the BODY tag. We could have placed this close to the elements that we actually want Angular so manage, but it is most simple, and not uncommon, to place it in the BODY tag.

Example # 2

In Example # 2, we have a text box (an input that has a type attribute of “text”), and a paragraph. We have provided an ng-model attribute for the input element, and provided a value of “myData”. Behind the scenes, Angular has created an object that is a private variable of a function, given it a property named “myData”, and bound the value of it to this element. Anything that we type into this textbox will become the updated value of the “myData” property, and when that same “myData” property is changed elsewhere, this textbox will reflect that new value. This two-way data-binding is one of the most powerful features of Angular.js. You’ll also notice that in the HTML of Example # 2, there is a set of double-curly braces, with the text “myData” inside of it. This tells Angular that the value of myData should go inside of the double-curly braces, and be updated whenever the value of myData changes. If you click the link below, it will take you to the JsFiddle.net link for the fully working demo of Example # 1’s code.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 2: http://jsfiddle.net/L69aq/

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.

Example # 3

In Example # 3, we have added a select element to the page. We have included an Angular ng-model directive and specified a value of “myData”. This means that the select element is bound to the exact same data as the two elements in Example # 2’s code.

If you click the link below, it will take you to the JsFiddle.net link for the fully working demo of Example # 3’s code.

HERE IS THE JS-FIDDLE.NET LINK FOR EXAMPLE # 3: http://jsfiddle.net/L69aq/1/

How to Demo: In addition to typing something in the text box, you can now select one of the options from the drop-down box. Now that SELECT element, 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.

Summary

In this article, we covered the bare-bones basics of data-binding in Angular.js. The key component here is the ng-model directive. We discussed how the ng-model directive creates a property of an object that is a private variable of a function, and bound to any element whose ng-model directive’s value is the same. We also demonstrated that when more than one element’s ng-model directive values are the same, there is a two-way data binding because when one element changes the value of the data, the rest of the elements bound to that data are updated, and vice versa.

This article merely scratches the surface of data-binding in Angular.js, but the hope is that it has provided a foundation upon which you can start to understand the incredibly powerful and elegant JavaScript library.

Helpful Links for Angular.js Data Binding Basics

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

http://docs.angularjs.org/api/ng.directive:ngModel

http://en.wikipedia.org/wiki/AngularJS#Two-way_data_binding