ngModel & Two way Data binding in Angular

In this article let us explore the two way data binding in Angular and how NgModel implements the two-way binding in Angular Forms. The ngModel is a built-in directive and is part of the FormsModule. The Two-way binding uses the syntax [()]

What is Two way data binding

Two way data binding means that changes made to our model in the component are propagated to the view and that any changes made in the view are immediately updated in the underlying component data.

Two way data binding is useful in data entry forms. Whenever a user makes changes to a form field, we would like to update our model. Similarly, when we update the model with new data, we would like to update the view as well

The two way data binding is nothing but both property binding & event binding applied together. Property Binding is one way from component to view. The event binding is one way from view to component. If we combine both we will get the Two-way binding.

Angular Two way binding using Property and event binding

Two way using property & Event Binding

The following example shows how we can achieve two-way binding using the combination of property binding & event binding

Create a new Angular application

copy the following code to app.component.html

Update the app.component.ts with the following code.

We bind the name property to the input element ([value]="name"). We also use the event binding (input)="name=$event.target.value". It updates the name property whenever the input changes. The Angular interpolation updates the {{name}}, so we know the value of name property.

$event.target.value raises the error Property ‘value’ does not exist on type ‘EventTarget’ if fullTemplateTypeCheck is set to true under angularCompilerOptions in the tsconfig.json.

The error is due to the fact that the value property is not guaranteed to exist in the $event.target.

To solve this problem either you can use the $any typecast function ($any($event.target).value) to stop the type checking in the template or set fullTemplateTypeCheck to false in tsconfig.json.

Two-way binding syntax

The above example uses the event & property binding combination to achieve the two-way binding. But Angular does provide a way to achieve the two-way binding using the syntax [()]. Note that both square & parentheses are used here. This is now known as Banana in a box syntax. The square indicates the Property binding & parentheses indicates the event binding.

For Example

The above syntax sets up both property & event binding. But to make use of it, the property must follow the following naming convention.

If we are binding to a settable property called someProperty of an element, then the element must have the corresponding change event named somePropertyChange

But most HTML elements have a value property. But do not have a valueChange event, instead, they usually have an input event. Hence they cannot be used in the above syntax

For Example, the following will not work as there is no valueChange event supported by the input element.

Hence we have a ngModel directive.

What is ngModel

The Angular uses the ngModel directive to achieve the two-way binding on HTML Form elements. It binds to a form element like input, select, selectarea. etc.

Internally It uses the ngModel in property, binding to bind to the value property and ngModelChange which binds to the input event.

How to use ngModel

The ngModel directive is not part of the Angular Core library. It is part of the FormsModule library. You need to import the FormsModule package into your Angular module.

In the template use the following syntax

The ngModel directive placed inside the square & parentheses as shown above. This is assigned to the Template Expression. Template Expression is the property in the component class

ngModel Example

Import FormsModule

Open the app.module.ts and make the following changes

Template

Component

The ngModel data property sets the element’s value property and the ngModelChange event property listens for changes to the element’s value.

Run the project and see that as you modify the name, the component class model is automatically updated.

Custom Two-way binding

As we mentioned earlier the [()] to work, we need to have a property with the change event as<nameofProperty>Change.

We do not have any HTML Elements which follows the above naming conventions, but we can create a custom component

create new component and name it as counter.component.ts. copy the following code.

The component has two properties one is input property count decorated with @Input(). The other in is an event (or output property), which we decorate with @Output(). We name the input property as count. Hence the output property becomes countChange

Now we can use this component and create two-way binding to the count property using the syntax [(count)].

Summary

The two-way binding is a simple, but yet powerful mechanism. We use Property binding & Event binding to achieve the two-way binding. Angular does have a [(value)] syntax to which sets up the two-way binding. It automatically sets up property binding to the value property of the element. It also sets up the event binding to valueChange Property. But since we hardly have any HTML element, which follows those naming conventions unless we create our own component. This is where ngModel directive from FormsModule steps in and provides two way binding to all the known HTML form elements.

13 thoughts on “ngModel & Two way Data binding in Angular”

  1. Pratheesh Russell

    We can add a directive like the following


    import { Directive, EventEmitter, HostListener, Output } from '@angular/core';

    @Directive({
    selector: '[appTwoWayInput]',
    })
    export class TwoWayInputDirective {
    @Output('valueChange') update = new EventEmitter();
    @HostListener('input', ['$event'])
    handleInputChange(event) {
    this.update.emit(event.target.value);
    }
    }

    and bind to value of inputs

  2. “The two way data binding nothing but both property binding & event binding applied together. Property Binding is one way from view to component. The event binding is one way from component to view”.

    It is incorrectly mentioned about the property and event binding direction. It needs a correction.

    1. But as per Angular.io Docs, Property binding moves a value in one direction, from a component’s property into a target element property. And Event binding lets you listen for and respond to user actions from view to component.

  3. Two way using property & Event Binding
    for this example getting this error
    Property ‘value’ does not exist on type ‘EventTarget’.
    for this line

    1. The error is due to typescript checking types in templates.

      You need to cast $event.target to any as shown below

      (input)=”name=$any($event.target).value

      Also, I have updated the article again with notes

  4. Hi @TEKTUTORIALSHUB,
    I found something wrong in What is Two way binding section. In third paragraph, it is written like… event binding is one way from component to view and Property Binding is one way from view to component which is WRONG.
    I hope u will correct it soon…
    By the way, your tutorials are awesome.
    Thank you _/\_

  5. There’s some missing code for the last section “Custom Two-way binding”.

    app.component.ts:

    import { Component } from '@angular/core';
    @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    count: number = 0;
    clearCount() {
    this.count = 0;
    }
    }

    Also if you generate your counter.component.ts automatically, the @Component.selector will be app-counter, make sure to rename it to counter to match the html in app.component.html ( )

    1. Instead of adding clearCount() to AppComponent, it should be added to CounterComponent class, as it has functionality related to the count property. Moreover, the below code should be added to the template section of CounterComponent:
      Current Count {{count}}
      Clear

      The AppComponent html file should only have tag.

Leave a Comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top