Search code examples
angularangular-ngmodelngmodel

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


Solution

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