Loss of two-way binding when clicking on an array inside a form (Angular 2)

I am building a basic CRUD application with Angular 2. One of the form fields is a set of ingredients. I have an addIngredient method that pushes the new Ingredient to my ingredients array. As soon as I click on the button that launches this method, the two-way binding seems to be lost. When viewing diagnostic data, everything looks correct, but the data is lost from the UI form (see gif below):

enter image description here

Relevant HTML:

 <div *ngFor="let ingredient of newRecipe.ingredients; let i = index; let f = first; let l = last"> <md-input type="text" id="ingredientName" name="ingredientName" [(ngModel)]="ingredient.name" placeholder="ingredient" required></md-input> <md-input type="text" id="ingredientAmount" name="ingredientAmount" [(ngModel)]="ingredient.amount" placeholder="amount" required></md-input> <select id="ingredientMeasurement" name="ingredientMeasurement" [(ngModel)]="ingredient.measurement" required> <option *ngFor="let measurement of measurements" [value]="measurement">{{measurement}}</option> </select> <button md-icon-button color="primary" *ngIf="l" (click)="addIngredient()"> <md-icon>add</md-icon> </button> <button md-icon-button color="warn" *ngIf="!f" (click)="removeIngredient(i)"> <md-icon>remove</md-icon> </button> </div> 

corresponding code from the class:

 addIngredient() { this.newRecipe.ingredients.push(new Ingredient()); } 

NOTE. div mentioned above appears inside the form element. When I move this div outside the form , everything works as expected.

+6
source share
1 answer

What happens here is that <form> uses the input properties of name to synchronize model values. In this case, it basically cancels the synchronization of [ngModel].

What you can do to fix this: make name dynamic:

 <div *ngFor="let ingredient of newRecipe.ingredients; let i = index;"> <md-input type="text" name="ingredientName_{{i}}" [(ngModel)]="ingredient.name" placeholder="ingredient" required> </md-input> </div> 

(i.e. name="ingredientName_{{i}}" )

Read more about this in the docs: https://angular.io/docs/ts/latest/api/forms/index/NgModel-directive.html

When using ngModel inside tags, you will also need to specify a name attribute so that the control can be registered using the parent form under that name.

It is worth noting that in the context of the parent form, you can often skip the one-way or two-way binding, because the parent form will synchronize the value for you.

+12
source

Source: https://habr.com/ru/post/1012470/


All Articles