Simplifying Two-Way Data Binding in Angular 2

There are three types of data bindings in Angular 2, they are as follows:

  1. Interpolation
  2. Event Binding
  3. Property Binding

If you are coming from Angular 1.X background, you might be wondering that where is the two-way data binding? Remember, when first time you saw AngularJS 1.X demo, and was just blown away by power of ng-model? Yes, like you, I was also very impressed by power of two-way data binding in AngularJS 1. Even though, AngularJS 1 two-way data binding was beautiful, it came with the baggage of digest cycle and $watch.

To simplify the things, Angular 2 does not have any built in Two-Way data binding. It does not mean; you cannot have two-way data binding in Angular 2 application. Come on, we cannot think of creating a modern web application without having power of two-way data binding. So, in this post, we are going to learn, how to work with two-way data binding in Angular 2.

image

Two-way data binding with ngModel

Angular 2 provides us a directive ngModel to achieve two-way data binding. It is very simple and straight forward to use ngModel directive as shown in the listing below:

To use ngModel directive, we need to import FormsModule in the application. For your reference, below I am listing app.module.ts which is importing FormsModule besides other required modules.

In above demo, when typing into the input element, the input’s value will be assigned to name variable and also it would be displayed back to the view. So we are implementing two-way data binding using ngModel as shown in the below image:

image

Two-way data binding without ngModel

To understand ngModel directive working, let us see how we can achieve two-way data binding without using ngModel directive. To do that, we need to use

  1. Property binding to bind expression to value property of the input element. In this demo, we are binding name variable expression to value property.
  2. Event binding to emit input event on the input element. Yes, there is an input event which will be fired whenever user will input to the input element. Using event binding, input event would be bind to an expression.

So, using the property binding and the event binding, two-way data binding can be achieved as shown in the listing below:

Same like ngModel directive demo in this demo also, when typing into the input element, the input element’s value will be assigned to name variable and also it would be displayed back to the view.

So we are implementing two-way data binding without using ngModel using the code shown in the below image:

image

Let us understand few important things here:

  1. [value]=”name” is the property binding. We are binding value property of the input element with variable (or expression) name.
  2. (input)= “expression” is event binding. Whenever input event will be fired expression will be executed.
  3. “name=$event.target.value” is an expression which assigns entered value to name variable.
  4. Name variable can be accessed inside AppComponent class.

So far we have seen two-way data binding using ngModel and without ngModel. We can conclude that the directive ngModel is nothing but combination of property binding and event binding. Event binding is denoted using small bracket and property binding is denoted using square [] bracket, and if you notice syntax of ngModel is [(ngModel)], which is like a banana put into a box suggests it is combination of both event and property binding.

image

Read full article on the Infragistics blog

Data Binding and Observable in WinJS

Source code on GitHub

In this post we will learn how to work with the data binding and observable class in the Windows Store application created using WinJS. We will learn to work with

  • Data binding
  • Two way data binding
  • Observable object

By default WinJS

  • Provides one way binding
  • When the data source is updated HTML element gets updated
  • Updated value of HTML element does not update the data source.

Let us start with working with a basic data binding example. So I have a JavaScript object as shown below,


var student = { name: "Dj" };

We can perform data binding in winJS using data-win-bind attribute on the HTML element.

clip_image002

In above code snippet we are using data-win-bind attribute to bind span inner text with the name property of the student object. As of now HTML is very simple and looks like as follows:


<body>
     <div id="welcome">
        Welcome,
        <span id="nameSpan"
              data-win-bind="innerText: name">
        </span>
    </div>

</body>

As the last step of the data binding we need to call WinJS.Binding.processAll() by passing the data source and the target HTML element. Make sure that you call this after the execution of all the activation codes.


    var personDiv = document.querySelector('#nameSpan');
    WinJS.Binding.processAll(personDiv, student);

Essentially we are selecting the element using the document.querySelector and the in the process all function passing the target element and the data source as a data context. By now we have successfully data bind html element to the data source. On running the application you should get output as follows

clip_image002[6]

So far we have done one way binding and if data changes at the data source target element won’t get any notification. We can convert a data context to a binding context using the WinJS.Binding.as. To understand this in better way let us start looking at a problem statement. I have modified the UI as follows,


<body>
    <div id="welcome">
        Welcome,
        <span id="nameSpan"
              data-win-bind="innerText: name">
        </span>
        <br/>
        <input type="text" id="txtInput" />
        <button id="btnUpdataDs">Update DataSource</button>
    </div>

</body>

Now UI look like as follows and when we enter a value in the text box that should update the welcome span.

clip_image002[8]

On the click event of the button we can modify name property as follows


document.querySelector("#btnUpdataDs").onclick = function () {

           var updatedname = document.querySelector('#txtInput').value;
           student.name = updatedname;
        }

When run the application you will find that value of the welcome span is not getting updated. Reason behind is that when data source is getting updated it does not send any notification to the target elements bind to it. WinJS gives us a method to create notification on the data source and convert it to a binding context. You need to use WinJS.Binding.as to create binding context.

So let us modify the above code to perform two way binding,

var personDiv = document.querySelector('#nameSpan');
        WinJS.Binding.processAll(personDiv, student);
        var bindingSource = WinJS.Binding.as(student);
        document.querySelector("#btnUpdataDs").onclick = function () {

           var updatedname = document.querySelector('#txtInput').value;
           bindingSource.name = updatedname;
        }

In above code there is only one extra added line

clip_image002[10]

Now on running the application you will find that when you change the value in text box and click on update data source value of welcome span will also be changed.

clip_image004

WinJS data bind allows us to to do binding of styles as well. Let us go ahead and add one more property to set the color of the text. Updated data source is as follows:

 


   var student = {
        name: "Dj",
        color: "red"
     };

And we can bind color to the welcome span as follows


<span id="nameSpan"
              data-win-bind="innerHTML: name;
               style.background: color ">
        </span>

And we can update value of color as follows

var personDiv = document.querySelector('#nameSpan');
        WinJS.Binding.processAll(personDiv, student);
        var bindingSource = WinJS.Binding.as(student);
        document.querySelector("#btnUpdataDs").onclick = function () {

           var updatedname = document.querySelector('#txtInput').value;
           bindingSource.color = updatedname;
        }

Now let us see that how can we bind to a complex object. We will start with creating a complex object. Working with complex object can be summarized into following steps

  1. Create the class
  2. Add _initObservable method in the constructor of the class
  3. Make class observable by using the WinJS.Class.mix
  4. Create instance of the object
  5. Use bind methods to bind the properties
  6. Use the object in the binding

Let us start with creating a Student class

 


var Student = WinJS.Class.define(
       function()
       {

           this.name = "DJ";
           this.size = "16px";
       },
       {

           _names:
               ["foo", "loo", "koo", "too", "moo", "soo", "aoo", "too", "qoo", "coo"],
           _sizes:
               ["30px", "80px", "40px","20px","35px","67px","43px","23px","54px","12px"],

           _newName: function () {
               this["name"] = this._names[this._randomizeValue(this._names.length)];
               this["size"] = this._sizes[this._randomizeValue(this._sizes.length)];
           },
           _randomizeValue: function (max) {
               return Math.floor((Math.random() * 1000) % max);
           }

       });

In this class we have put two arrays and two functions. In the constructor of the class we are setting default value for name and the size. _newName function will return new name from the array with new size from the size array.

Next we need to add _initObservable inside the constructor. So updated constructor will look like as follows:

 


  var Student = WinJS.Class.define(
       function()
       {
           this._initObservable();
           this.name = "DJ";
           this.size = 16;
       },

Now to make the object observable we need to use WinJS.Class.mix. This can be done as follows:


    WinJS.Class.mix(Student,
    WinJS.Binding.mixin,
    WinJS.Binding.expandProperties({name: "", size: ""})
);

After this step we need to call the bind method on the instance of the Student class. Make sure to create instance in the app.onactivated event handler.

 

            var s = new Student();
            s.bind("name",onNameChange);
            s.bind("size", onSizeChange);

The bind method takes two parameters. First name of the property and second parameter as the function which will define how property will be bind. Below we have function calling on the bind.


function onNameChange (newValue) {
        var span = document.getElementById("nameSpan");
        span.innerText = newValue;
    };

    function onSizeChange (newValue) {
        var span = document.getElementById("nameSpan");
        span.style.fontSize = newValue;
    };

On the HTML markup is bind to properties of Student and there a button. On click event of the button we will call _newName function on the student object to change the name and the font size.


   <div id="welcome">
        Welcome,
        <span id="nameSpan"
              data-win-bind="innerHTML: name;
               style.fontsize: size ">
        </span>
        <br/>
        <button id="btnUpdataDs">Update DataSource</button>
    </div>

On the click event of the button we will call _nameName function as shown below:

document.querySelector("#btnUpdataDs").onclick = function () {

            s._newName();
        }

When you run the application on the click of the button name and size of the name should change. Data binding and the observable are very important components of WinJS and you may want to use them while create app for the Windows Store.

Source code on GitHub

Happy Coding.