简体   繁体   中英

Angular 5 populate data with FormArray

In angular 5 I have made the functionality for add new row and remove row by using formarray. Its working fine for now. But lets say I have some data and I want to show them in the rows one by one so lets say I have data for 3 rows so the form should automatically show 3 rows by default with all the values populated in it with add and remove row functionality.

This is the code what I have done so far

app.component.html looks like this

<div class="container col-md-12">
  <h1 class="page-header">Create Event</h1>
  <div class="row show-hide-message">
    <div [ngClass]= "messageClass">{{message}}</div>
  </div>
  <form [formGroup] = "form" (ngSubmit)="onEventSubmit()">
  <fieldset>
    <div class="form-group">
      <label for="eventname">Event Name</label>
      <div class='form-group' [ngClass]="{'has-error': form.controls.eventname.errors && form.controls.eventname.dirty, 
  'has-success': !form.controls.eventname.errors
}">
        <input type="text" class="form-control" autocomplete="off" placeholder="Event Name" formControlName="eventname">
        <ul class="help-block">
          <li *ngIf="(form.controls.eventname.errors?.minlength ) && form.controls.eventname.dirty">Event name should be atleast 5 characters</li>
        </ul>
      </div>
    </div>


    <h4>Package Price</h4>
    <hr>
    <div class="row" formArrayName="sections">
      <div class="col-md-12" *ngFor="let section of getSections(form); let i = index" [formGroupName]="i">
        <div class="form-group col-md-5">
          <label for="packagename">Package Name</label>
          <input type="text" class="form-control" autocomplete="off" placeholder="Package Name" formControlName="packagename"  >
       </div>
        <div class="form-group col-md-2">
          <label for="packageprice">Package Price</label>
          <input type="number" class="form-control" autocomplete="off" placeholder="Package Price" formControlName="packageprice" >
        </div>
        <div class="form-group col-md-2">
          <label for="packagelimit">Max Purchase Limit</label>
          <input type="number" class="form-control" formControlName="packagelimit" autocomplete="off" >
        </div>
        <div class="form-group col-md-1">
          <br/>
          <input type="button" (click)="addPackageRow()" class="btn btn-md btn-success" value="+" name="">
        </div>
        <div class="form-group col-md-1" *ngIf="getSections(form).length > 1">
          <br/>
          <input type="button" (click)="removeSection(i)" class="btn btn-md btn-error" value="-" name="">
        </div>
      </div>
    </div>

    <input [disabled]=!form.valid type="submit" class="btn btn-primary" value="Submit">

    <pre>{{form.value | json}}</pre>

  </fieldset>
</form>
</div>

app.component.ts looks like this

import { Component, OnInit } from '@angular/core';
import { FormArray, FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  form :  FormGroup;
  packagesArray: FormArray;

  storageData = [
    {"packagename":"Package One","packageprice":12,"packagelimit":9},
    {"packagename":"Package Two","packageprice":78,"packagelimit":5},
    {"packagename":"Package Three","packageprice":89,"packagelimit":7}
];

  constructor(
    private formBuilder : FormBuilder,
    ) { this.createEventForm() }

  createEventForm() {
    this.form = this.formBuilder.group({
      eventname: ['', Validators.compose([
        Validators.required,
        Validators.minLength(5)
      ])],
      packages: this.packagesArray
    })
  }

  ngOnInit() {
    this.form = new FormGroup({
      eventname: new FormControl(''),
      sections: new FormArray([
        this.initSection(),
      ]),
    });
  }

  initSection() {
    return new FormGroup({
      packagename: new FormControl(''),
      packageprice: new FormControl(''),
      packagelimit: new FormControl('')
    });
  }

  initItemRows() {
        return this.formBuilder.group({
            itemname: ['']
        });
    }

  onEventSubmit() {}

  public addPackageRow() {
    const control = <FormArray>this.form.get('sections');
    control.push(this.initSection());
  }


  addSection() {
    const control = <FormArray>this.form.get('sections');
    control.push(this.initSection());
  }

  getSections(form) {
    return form.controls.sections.controls;
  }

  public removeSection(i){
   const control = <FormArray>this.form.get('sections');
   control.removeAt(i);
  }

}

So can someone tell me how to do this? Any help and suggestion will be really appreciable. Thanks

I just want to populate data of storageData with the respective rows.

Here is the working demo

https://stackblitz.com/edit/angular-mh3dpy

I would go with:

this.form = new FormGroup({
  eventname: new FormControl(''),
  sections: new FormArray(this.storageData.map(item => {
    const group = this.initSection();
    group.patchValue(item);
    return group;
  }))
});

Ng-run Example

Change your ngOnInit :-

    ngOnInit() {
    this.form = new FormGroup({
      eventname: new FormControl(''),
      sections: new FormArray([
        this.initSection(),
      ]),
    });

    var data;
    for(data in this.storageData){
      console.log(this.storageData[data]);
      var temp = {};
      for(var k in this.storageData[data]){
        //console.log(k);
        temp[k] = new FormControl(this.storageData[data][k]);
      }
      console.log(temp);
      var formGrp = new FormGroup(temp);

      const control = <FormArray>this.form.get('sections');
      control.push(formGrp);
    }
  }

puff, I suggested make a functión that return the formArray

//this.fb is in the constructor private fb:FormBuilder
getSeccion(storageData: any[]): FormArray {
    //create an arr of FormGroup
    //each element of array storageData transform in a FormGroup
    const arr = storageData.map(data => {
        return this.fb.group({
            packagename: [data.packagename,Validators.Required], //<--e.g. if Required
            packageprice: [data.packageprice],
            packagelimit: [data.packagelimit]});
    })
    //return a FormGroup with this array
    return this.fb.array(arr);
}

So, your ngOnInit

ngOnInit() {
    this.form = new FormGroup({
      eventname: new FormControl(''),
      sections: this.getSeccion(this.storageData )
    });

MoreOver, if you has an object

mydata={eventname:'myEvent',
        sections:[{packagename:'name1',packageprice:'100',packagelimit:30},
        {..},
        {..}..]

You can use

this.form = new FormGroup({
      eventname: new FormControl(this.myData.eventname),
      sections: this.getSeccion(this.myData.storageData )
    });

Well, normally we get data from database. So our ngOnInit can be some like

ngOnInit()
{
    myservice.getData().subscribe((res:any)=>{
          this.data=res  //normally we can save the data in a variable
          this.form = new FormGroup({
              eventname: new FormControl(res.eventname),
              sections: this.getSeccion(res.storageData )
           });
    })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM