ngModel and two-way binding in Angular

Introduction

The most awesome feature in Angular is two-way data binding. The directive which supports this data binding is ngModel. The value in the UI is changed if there is any change in the model or vice versa. Both the values are synced. ngModel creates the instance of FormControl from the model and binds it to a form control element. The instance created by ngModel tracks the user validations, state of the input field, interaction, etc. 

ngModel

ngModel actually implements two-way data binding. It comes with event binding as well as property binding. It is used as a banana in a box-model as syntax [(ngModel)]. 
  • We can use ngModel for adding validations to form control fields such as input boxes, select-box, etc.
  • It will bind the value in the model with the view. If the model is changed, it automatically updates the value in the view. Binding view to model and vice-versa.
  • It either uses [()] or -bind syntax to represent two-way binding in Angular.
  • It is necessary to specify a name attribute when using ngModel within the form tag. Otherwise, it will give an error.

Two-way data binding in Angular Example

We will now implement two-way data binding with an example below:)

<div>
 <label class="req">Customer name</label>
              <div>
                <input [(ngModel)]="custName" #custName="ngModel" placeholder="Enter customer name"/>
              </div>
</div>

Now we have used the [(ngModel)] syntax for two-way binding(ngModel banana in a box-model). This comes with property and event binding. If we see the underlying implementation of [(ngModel)], then it behaves the following way:

<div>
 <label class="req">Customer name</label>
              <div>
                <input [ngModel]="custName" (ngModelChange)="custName = $event"
                  #custName="ngModel" placeholder="Enter customer name"/>
              </div>
</div>

Here in the above example, property binding is done using [ngModel] syntax. It binds the DOM element with the model. The event binding (ngModelChange) notifies the user when there is a change in the view. Moreover, the handler is using $event rather than $event.target.value. It will extract the value from the inner payload of $event. It extracts and emits the value. Event binding will take care of extracting value from the inner $event payload.

NOTE: Angular two-way binding not working

Error when we use ngModel in the <form> tag without name attribute specified.


The most important note regarding the model is that if we are using it inside any <form> tag, then the name attribute should be specified. The name attribute is defined so that the control of that particular field is assigned under parent form with that name. 

Using ngModel for Validations

We can bind the control to a variable name using ngModel. Using this variable we can check for different validations. We can see this using the following example:

<label for="" class="req">Display name</label>
    <input placeholder="Enter site display name"  name="displayName"
      [(ngModel)]="siteDisplayName" #siteName="ngModel"
      [pattern]="[A-Z]" minlength="2" maxlength="80" />
                                  
           <small class="text-danger"  *ngIf="siteName.errors?.valid >
                    Site name is not valid.
            </small> 
            <small class="text-danger" *ngIf="siteName.errors?.pattern">
                    The site name should have only alphabets.
            </small> 

In the above example, we have bound the control using #siteName="ngModel". This is called the template variable reference. This variable will track the status of this field. We can use this reference to show errors to the user.

ngModel in a Form

We can see the below example for using ngModel inside a form tag. We need to specify the name attribute with ngModel. 

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

@Component({
  selector: 'example-app',
  template: `
<form (ngSubmit)="onSubmit(siteForm)" #siteForm="ngForm">
   <input placeholder="Enter site display name"  name="displayName"
      [(ngModel)]="siteDisplayName" #siteName="ngModel"
      [pattern]="[A-Z]" minlength="2" maxlength="80" />

          <div>
         <small class="text-danger"  *ngIf="siteName.errors?.valid >
                    Site name is not valid.
            </small> 
            <small class="text-danger" *ngIf="siteName.errors?.pattern">
                    The site name should have only alphabets.
            </small> 
       </div>

      <button>Submit</button>
    </form>

<div></div>
  `,
})
export class SimpleFormComp {
  onSubmit(f: NgForm) {
    console.log(siteForm.value);  
    console.log(siteForm.valid);  
  }
}

Comments