Simplifying Custom 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.

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:

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <input [(ngModel)]='name' />
      <br/>
      <h1>Hello {{name}}</h1>
  </div>
  `
})
export class AppComponent{


}

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.

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';

@NgModule({
    imports:      [ BrowserModule,FormsModule ],
    declarations: [ AppComponent],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }

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:

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:

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <input [value]="name" (input)="name=$event.target.value" />
      <br/>
      <h1>Hello {{name}}</h1>
  </div>
  `
})
export class AppComponent{

        name : string = "";
    }

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:

 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.

Custom two-way data binding

We should be very careful whether to create a custom two-way data binding or rely on ngModel directive. We really don’t have to create custom two-way data binding always. However, it is good to know steps to create a custom two-way data binding. Let us create a customcounter component with two-way data binding enabled. Let us follow the steps:

 Step 1

Create a component with two buttons and methods to increment and decrement.  

@Component({
    moduleId: module.id,
    selector:'countercomponent',
    template:`
    <button (click)='increnent()'>Increment</button>
    {{count}}
    <button (click)='decrement()'>Decrement</button>
    `
})
export class  AppChildComponent {

        count : number = 0;      
        increment(){

            this.count = this.count+1; 
        }

        decrement(){
            this.count = this.count - 1; 
        }
    }

Above we have created a very simple component to increment and decrement the count. Now very much we can use this component inside another component, however two-way data binding is not enabled on this component.  To enable that, we need to use @Input and @Output properties.

 Step 2

Let us create a getter with @Input() property. This getter will return the count. Since it is attributed with @Input() decorator, consumer of this component can bind this value using the property binding.

@Input() 
    get counter(){

        return this.count; 
    }


Step 3

To create two-way data binding, we need to create an event of the type EventEmitter. This event is attributed with @Output() decorator such that it can be emitted to the consumer component. We are creating event object in the constructor of the component.

@Output() counterChange :  EventEmitter<number>;
    constructor(){
         
        this.counterChange = new EventEmitter();
         
    }


Step 4

As last step, increment and decrement functions should emit counterChange event. So, we need to modify increment and decrement function as shown in the listing below:

   increment(){

        this.count = this.count+1; 
        this.counterChange.emit(this.count);
    }

    decrement(){
        this.count = this.count - 1; 
        this.counterChange.emit(this.count);
    }

Both functions are emitting counterChange event. Putting every pieces together, a component with custom two-way data binding will look like code listed below:

import {Component,Input,Output,EventEmitter} from '@angular/core';

@Component({
    moduleId: module.id,
    selector:'countercomponent',
    template:`
    <button (click)='increment()'>Increment</button>
    {{count}}
    <button (click)='decrement()'>Decrement</button>
    `
})
export class  AppChildComponent {

        count : number = 0;   

     @Output() counterChange :  EventEmitter<number>;
        constructor(){
         
            this.counterChange = new EventEmitter();
         
        }
     
     @Input() 
        get counter(){

            return this.count; 
        }

        increment(){

            this.count = this.count+1; 
            this.counterChange.emit(this.count);
        }

        decrement(){
            this.count = this.count - 1; 
            this.counterChange.emit(this.count);
        }
    }


Step 5

Like any simple component, a component with two-way data binding can be used inside another component.

import {Component} from '@angular/core';

@Component({
    moduleId:module.id,
    selector:'my-app',
    template:`
  <div class="container">
     <br/>
    
     <countercomponent [(counter)]="c"></countercomponent>
     <br/>
     <h2>count = {{c}}</h2> 
     
  </div>
  `
})
export class AppComponent{

        c : number = 1; 
      
    }

The main thing you may want to notice the way value of counter property is set inside AppComponent. Like ngModel directive, counter property is also set using the banana in box syntax [(counter)]

Conclusion

Two-way data binding in Angular 2 is supported using the event and the property binding. There is no in-built two-way data binding. We can use ngModel directive to use two-way data binding. Also, if required custom two-way data bindings can be created. Custom two-way data binding us useful in form controls.

In this post, we learnt about ngModel and creating custom two-way data binding. I hope you find this post useful. Thanks for reading.


Comments  (6 )

Rhyta Paul
on Mon, Dec 12 2016 4:42 AM

I guess 2-way binding is a major feature of Angular 1.0, Does this post denote that somehow 2-way binding in Angular 1.0 was not a useful feature? Can you plz clear why we should not opt for the 2-way binding?

Lauri Pini
on Wed, Dec 14 2016 12:12 PM

yes do it please

Carlos Lopez
on Thu, Feb 9 2017 6:05 AM

Thanks for the post clarifying the topic, but actually there is something wrong.

Unless you include the setter method inside the child component, it will be just a one-way-data-binding relationship from child to parent and the original value of "c" will not pass to countercoponent on the first time and it will start with 0 always.

joney wakker
on Sun, Feb 26 2017 3:26 AM

Here include about the data binding.this blogs are really very useful for all students.it include more relevant and normal informations.i am very happy to visit this site.i got a different type of more relevant informations.propertychoice.in/Property.php

lyrin john
on Sun, Feb 26 2017 10:08 AM

Here include about the data binding based informations.i got a clear informations about the data binding in this blog.thanku so much for including this topic.shabdhaclinic.com/hearing-aid-&-speech-therapy

stephen
on Sat, Mar 25 2017 12:11 AM

Here described about the data binding based program and informations.the data binding informations are clearly explained in this article.this program is easily understand by all students.its really useful for me. http://collegesniper.com/

Add a Comment

Please Login or Register to add a comment.