angulardata-bindingangular-formsngmodelproperty-binding

Angular, [(ngModel)]="abc", unknown how the part (ngModel)="abc" works


In Angular, [(ngModel)]="abc", I know this mean two way binding, change value abc in model (ts) will reflect in view (html), change the view value will update the value in model, as tested in case 5 in following example. I also know [ngModel]="abc" means if model "abc" value is changed, the view will update accordingly, as tested in case 1 in following example.

  1. But I don't know in [(ngModel)]="abc", how the view change (html) update the model (ts) value?

I have seen the question

[https://stackoverflow.com/questions/46120731/angular-ngmodel-vs-ngmodel-vs-ngmodel][1]

it mention

[(ngModel)]="expression"

is unwrapped by the compiler into

[ngModel]="expression" (ngModelChange)="expression=$event"

in my case, expression is "abc", so I try to simulate in case 2,3,4 (especially case 3), but all cannot reflect the change from view to model.

the testing code is as follow:
test-binding1.component.ts

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

@Component({
  selector: 'app-test-binding1',
  templateUrl: './test-binding1.component.html',
  styleUrls: ['./test-binding1.component.css']
})
export class TestBinding1Component implements OnInit {

  constructor() { }
  abc:string = "2";

  ngOnInit() {
  }

}

test-binding1.component.html

<p>case 1: Input with [ngModel]:<input type="text" [ngModel]="abc"/></p>
<p>case 2: Input with (ngModel):<input type="text" (ngModel)="abc"/></p>
<p>case 3:Input with (ngModelChange)="expression=$event":<input type="text" 
    (ngModelChange)="abc=$event"/></p>
<p>case 4:Input with (ngModelChange)="$event":<input type="text" 
        (ngModelChange)="$event"/></p>
<p>case 5:Input with [(ngModel)]:<input type="text" [(ngModel)]="abc"/></p>
<p>case 6:{{abc}}</p>

when visit the test-binding1.component.html, case 1, 5, 6 shows 2 initially, case 2,3,4 show blank.
If I update the textbox value in case 5, textbox value in case 1, 6 change according, textbox value in case 2,3,4 has no effect.
if update value in textbox case 1,2,3,4, no any change in other textbox value.


Solution

  • Below is the selector for ngModel

    ngModel.ts - source code

    @Directive({
      selector: '[ngModel]:not([formControlName]):not([formControl])',
      providers: [formControlBinding],
      exportAs: 'ngModel',
      standalone: false,
    })
    export class NgModel extends NgControl implements OnChanges, OnDestroy {
    

    As you can see, the ngModel must be present only then (ngModelChange) will work.

    The (ngModel) will not work, since it first does not match the selector (I think).

    <p>case 2: Input with (ngModel):<input type="text" (ngModel)="abc"/></p>
    

    Full Code:

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      imports: [FormsModule],
      template: `
        <p>case 1: Input with [ngModel]:<input type="text" [ngModel]="abc"/></p>
        <p>case 2: Input with (ngModel):<input type="text" (ngModel)="abc"/></p>
        <p>case 3:Input with (ngModelChange)="expression=$event":<input type="text" [ngModel]="abc"
            (ngModelChange)="abc=$event"/></p>
        <p>case 4:Input with (ngModelChange)="$event":<input type="text" [ngModel]="abc"
                (ngModelChange)="$event"/></p>
        <p>case 5:Input with [(ngModel)]:<input type="text" [(ngModel)]="abc"/></p>
        <p>case 6:{{abc}}</p>
      `,
    })
    export class App {
      abc: string = '2';
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo