Venkatesh Prasath
Venkatesh Prasath

Reputation: 3

ngModel Overwrites the previous value while using in ng-For

This is my html file

<form [formGroup]='itemUpdateForm'>
      <div class="row">
        <mat-form-field class="col-sm-8">
            <mat-label>Restaurant Name:</mat-label>
            <input matInput type="text" required  [(ngModel)]="this.restuarantService.selectedProduct.name"   placeholder="Enter Restaurant Name" formControlName='name'>
        </mat-form-field>
      </div>

      <div class="row" *ngFor='let index of counter(this.restuarantService.selectedProduct.Items.length) ;let i = index' formGroupName='Items'>
        <mat-form-field class="col-sm-5">
          <mat-label>Food Name:</mat-label>          
          <input matInput type="text" required  [(ngModel)]='this.restuarantService.selectedProduct.Items[i].foodName'   placeholder="Enter Food Name" formControlName='foodName'>
      </mat-form-field>
      <mat-form-field class="col-sm-5" >
        <mat-label>Price:</mat-label>
        <input matInput type="text" required  [(ngModel)]="this.restuarantService.selectedProduct.Items[i].price"   placeholder="Enter Price" formControlName='price'>
      </mat-form-field>
      </div>
      
    </form>

And My Output looks like this Output

The Last value overwrites the previous values in all the fields. So I'm getting the last value in all the fields..I want to display all the values in order.What change i need to do

Upvotes: 0

Views: 402

Answers (1)

Eliseo
Eliseo

Reputation: 57929

Venkatesh, you has a type error. If you use formBuilder, is

this.formBuilder.group({
 name: this.restuarantService.selectedProduct.name
 ...
})

If you use the constructors of FormGroup and FromControl you use

new FormGroup({
 name: new FormControl({value:this.restuarantService.selectedProduct.name})
 ...
})

or

new FormGroup({
 name: new FormControl(this.restuarantService.selectedProduct.name)
 ...
})

Well the another problem in your code is that you need use a FormArray for the "items", see e.g. this SO

UPDATE see that it's always the same

1.- create a getter that return the formArray

  get itemsArray()
  {
    return this.itemUpdateForm.get('Items') as FormArray
  }

2.-Create an auxiliar function that allow us to create a formGroup

  createGroupItem(data:any=null)
  {
    data=data || {foodName:'',price:0}
    return this.formBuilder.group({
      foodName:data.foodName,
      price:data.price
    })
  }

Before the setValue you need add so many elements to the formArray as the "items"

setValue() {
    //before setValue, to a FormArray you need that the 
    //formArray has as many element as the data
    this.restuarantService.selectedProduct.Items.forEach(
          x=>this.itemsArray.push(this.createGroupItem()))

    //if the object not match exactly with the object use patchValue, not setValue
    //see how we pass the "Items", simply indicate the items
    this.itemUpdateForm.patchValue({
      name: this.restuarantService.selectedProduct.name,
      Items: this.restuarantService.selectedProduct.Items
    });
  }

The .html

<!--a div with formArrayName-->
<div formArrayName="Items">
    <!--iterating over the formArray.controls using the getter
        and use [formGroupName] -->
    <div *ngFor="let control of itemsArray.controls;let i=index"
            [formGroupName]="i">

        <!--the inputs with formControlName, see that in this case 
            is not enclosed by []-->
        <input formControlName="foodName">
        <input formControlName="price">
    
    </div>
</div>

Your forked stackblitz with the changes

NOTE: Really I like create also a new function that return the formGroup fully

createGroup(data:any=null)
{
   data=data ||{name:'',Items:null)
   return this.formBuilder.group({
        name:data.name,
        Items:data.items?this.formBuilder.array(
               items.map(x=>this.createGroupItem(x)):
       this.formBuilder.array([])
   })
}

And in ngOnInit()

itemUpdateForm=this.createGroup(his.restuarantService.selectedProduct)

Upvotes: 1

Related Questions