Search code examples
angular2-way-object-databindingngmodel

Angular2 ngModel two way binding does not work


I want to bind a model inside a ngFor loop to an input field via ngModel, but if I add another item to my list the value of the model will be visible in the model, but not in the view.

<div *ngFor="let model of models">
    <input [(ngModel)]="model.foo" name="foo">
    {{model | json}}
</div>
<button (click)="addEmptyListItem()">add</button>

If I enter bar in the view model | json will show { 'foo': 'bar' }, now if I add another element to the list model | json will still show { 'foo': 'bar' }, but nothing is visible in the input field.

My models variable comes from a BehaviorSubject

private $models: BehaviorSubject<Model[]> = new BehaviorSubject([]);
get models(): Model[] { return this.$models.getValue(); }

public addEmptyListItem(): void { 
    let models = this.models();
    models.push(new Model());
    this.$models.next(models);
}

which contains a list of Model

export class Model { public foo: string; }

Now if I exchange the [(ngModel)]="model.foo" name="foo" with [value]="model.foo" (input)="model.foo = $event.target.value":

<div *ngFor="let model of models">
    <input [value]="model.foo" (input)="model.foo = $event.target.value">
    {{model | json}}
</div>
<button (click)="addEmptyListItem()">add</button>

the view gets updated properly.

Question

Is there something I'm overlooking why [(ngModel)] isn't working?

And shouldn't [(ngModel)] also generate something similar to the above mentioned (see Two-way data binding in Angular 2)?


Solution

  • The name attribute has to be unique inside *ngFor loop., which you can make with index.

    Change your code like:

    <div *ngFor="let model of models;let i = index"">
        <input [(ngModel)]="model.foo" name="foo{{i}}">
    </div>