Populating Angular's Reactive form with data from server

Viewed 3369

Trying to insert server data into Angular's form so that the FormGroup property key is that from the server data. Followed Angular's docs on dynamic forms but it wasn't exactly what i wanted (https://angular.io/guide/reactive-forms#creating-dynamic-forms).

The point is to populate the form with the data and display it in template with *ngFor using sliders on each property to get a value. Then sending the data back to server.

Example of the data object:

{
  "things": [
    {
      "thingId": 1,
      "thingName": "bear"
    },
    {
      "thingId": 2,
      "thingName": "piano"
    }
  ]
}

Service getting the data and assigning to variable:

things: IThing[] = [];

getThings() {
  this.thingService.getThings()
    .subscribe(data => {
      this.things = data.things;
    });
}

I need to populate the things FormGroup (or FormArray if needed) with the values from the data object fetched from the server, that is, the thingName property value => "bear", "piano".

ngOnInit() {
  this.myForm = this.fb.group({
    title: ['', []],
    comment: ['', []],

    // need to populate the things object here, example:
    things: this.fb.group([
      // bear: [,[]],
      // piano: [,[]]
      // and so on...
    ])
  })

  this.getThings();
}
1 Answers

You can create a empy FormGroup and use addControl to add a control with a property name

things: this.fb.group({}) //<--a empty formGroup

And in the subscribe of the things

this.thingService.getThings()
    .subscribe(data => {
      this.things = data.things;
      this.things.forEach(x=>{
          (this.myForm.get('things') as FormGroup)
                 .addControl(x.thingName,this.fb.control(''))
      })
    });

NOTE: In .html you has some like

<form [formGroup]="myForm">
  ...
  <div formGroupName="things">
      <div *ngFor="let thing of things">
          <input [formControlName]="thing.thingName">
      </div>
  </div>
</form>

Update Another thing is that you really want has an FormArray, you need think about you database (if you want to store in a database). In this case you only need a FormArray of FormControls, so, at first you create a empty FormArray

things: this.fb.array([]) //<--a empty formArray

And, in subscribe you add to your formArray so many controls as elements has the things

this.thingService.getThings()
    .subscribe(data => {
      this.things = data.things;
      this.things.forEach(x=>{
          (this.myForm.get('things') as FormArray)
                 .push(this.fb.control(''))
      })
    });

And the .html like

<form [formGroup]="myForm">
  ...
  <div formArrayName="things">
      <div *ngFor="let controls of thingsArray.controls;let i=index">
          {{things[i].thingName}}:<input [formControlName]="i">
      </div>
  </div>
</form>

Use a getter to get the array

get thingsArray()
  {
    return this.myForm.get('things') as FormArray
  }

I put both cases in the stackblitz -in the stackblitz you has myForm and myForm2-

Related