0

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)?

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you very much! Is this documented somewhere - I was searching the angular documentation, but couldn't find this bit of information anywhere?
this is not actually documented on angular website, but since core concept of angular is to use native HTML attributes\event, So this is actually the behaviour of HTML to have unique name inside form tag., and since ngModel works only after importing FormsModule, so it uses that behaviour., also same we did in ng-repeat for angularjs1.x
Just found a case where name="foo{{i}}" is not working - if I want to remove an element from my list (e.g. the first element of a list with 2 elements) and add another element, then the first element will be inside my model but is not displayed in the view (I think because the index changed).
index will always remain unique, when you delete the element, then name property will change for every element inside *ngFor,
I followed your example, but it does not work if I delete an element (data not shown) - how can I fix this, or should I just use [value]="model.foo" (input)="model.foo = $event.target.value"?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.