2

I created the following form in order to add items to an array of ingredients. When the user clicks " Add a new Ingredient ", an empty ingredient is added to the list.

HTML:

<button md-button
              (click)="addIngredient()">
        <md-icon>add</md-icon> ADD
      </button>

    <div *ngFor="let ingredient of ingredients">
        <md-form-field floatPlaceholder="never">
          <input mdInput placeholder="NAME"
                 [(ngModel)]="ingredient.name" name="name">
        </md-form-field>
        <md-form-field floatPlaceholder="never" style="width: 80px">
          <input mdInput placeholder="QUANTITY" type="number"
                 [(ngModel)]="ingredient.quantity" name="quantity">
        </md-form-field>
    </div>

TS:

addIngredient() {
// outputs real list
console.log(this.ingredients);
this.ingredients.push({
      name: 'tt',
      quantity: '12'
    });
}

The app starts, and I click "Add" to add a new empty ingredient to the list. I updated the ingredient name and quantity, and then click "ADD" again to add another ingredient.

when I click the "ADD" button to add another ingredient, the form inputs of all the previous ingredients I added are set to the values I declared in the addIngredient() method (all names are showing as 'tt' and quantity is '12') although console log shows the real list.

Any idea what causes this issue?

TheUnreal
  • 23,434
  • 46
  • 157
  • 277

2 Answers2

2

When you use input/ngModel inside ngFor, you have to give unique value for attribute name of each input, so you have to generate unique id for each ingredient (I provided an exemple function that generate unique id):

<button md-button (click)="addIngredient()">
    <md-icon>add</md-icon> ADD
</button>

<div *ngFor="let ingredient of ingredients">
    <md-form-field floatPlaceholder="never">
      <input mdInput placeholder="NAME"
             [(ngModel)]="ingredient.name" name="name-{{ingredient.id}}">
    </md-form-field>
    <md-form-field floatPlaceholder="never" style="width: 80px">
      <input mdInput placeholder="QUANTITY" type="number"
             [(ngModel)]="ingredient.quantity" name="quantity-{{ingredient.id}}">
    </md-form-field>
</div>

addIngredient() {
    this.ingredients.push({
        id: this.guid(),
        name: 'tt',
        quantity: '12'
    });
}

private guid() {
    let uniqueId = Math.random().toString(36).substring(2) 
       + (new Date()).getTime().toString(36);
    return uniqueId;
}
Faly
  • 13,291
  • 2
  • 19
  • 37
0

You might need to add an index in your ngFor, I dont really know how to explain the behavior of ngFor with indexation, but keeping an eye on which item of the array you are may work :

<button md-button
          (click)="addIngredient()">
    <md-icon>add</md-icon> ADD
  </button>

<div *ngFor="let ingredient of ingredients; let i = index">
    <md-form-field floatPlaceholder="never">
      <input mdInput placeholder="NAME"
             [(ngModel)]="ingredients[i].name" name="name">
    </md-form-field>
    <md-form-field floatPlaceholder="never" style="width: 80px">
      <input mdInput placeholder="QUANTITY" type="number"
             [(ngModel)]="ingredients[i].quantity" name="quantity">
    </md-form-field>
</div>

EDIT : I based my answer on this post (Angular2 ngModel against ngFor variables)