Angular 2/4 Edit Form Populate FormArray Controls

Some changes to DeborahK's answer, since expense.expense_expense_categories doesn't contain a primitive types, but objects. Therefore we cannot assign the values as is, but each object needs to be wrapped in a FormGroup, just like you have attempted.

Here I have a shortened version of your code:

Build the form:

ngOnInit() {
  this.expenseEditForm = this.fb.group({
    notes: [''],
    // notice below change, we need to mark it as an formArray
    expense_expense_categories_attributes: this.fb.array([])
})

Then we call patchForm in the callback, just like you have. That function would look like this, notice, we call this.setExpenseCategories outside:

patchForm() {
  this.expenseEditForm.patchValue({
    notes: this.expense.notes,
  })
  this.setExpenseCategories()
}

Then comes the biggest change from your existing code, where we first assign the FormArray to the variable control and then we iterate your array received from backend, create a FormGroup for each object and push the object to each FormGroup:

setExpenseCategories(){
  let control = <FormArray>this.expenseEditForm.controls.expense_expense_categories_attributes;
  this.expense.expense_expense_categories.forEach(x => {
    control.push(this.fb.group(x));
  })
}

Then to the template, this example is without Angular Material:

<form [formGroup]="expenseEditForm">
  <label>Notes: </label>
  <input formControlName="notes" /><br>
  <!-- Declare formArrayName -->
  <div formArrayName="expense_expense_categories_attributes">
    <!-- iterate formArray -->
    <div *ngFor="let d of expenseEditForm.get('expense_expense_categories_attributes').controls; let i=index"> 
      <!-- Use the index for each formGroup inside the formArray -->
      <div [formGroupName]="i">
      <label>Amount: </label>
        <input formControlName="amount" />
      </div>
    </div>
  </div>
</form>

Finally a

Demo


If I understand your question correctly, you may need something like this:

    // Update the data on the form
    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));

You can see the complete example here: https://github.com/DeborahK/Angular2-ReactiveForms in the APM - Updated folder.