Search code examples
angularangular-reactive-formsformarray

formArray - Cannot find path to array of arrays


My FormGroup has this structure

asyncValidator: null
     controls: Object
       arr: FormArray
       asyncValidator: null
         controls: Array[6]
           0: FormGroup
           asyncValidator: null
           controls: Object
             name: FormControl
             pay: FormControl
             scores: FormArray
             asyncValidator: null
              controls: Array[3]
                0: FormControl
                   ...
                   value: 1
                   ...
                1: FormControl
                2: FormControl
                errors: null
                   ...

What is the proper html syntax to access the FormControl and values of the "scores" FormArray

I've tried many combinations of the html below without success

{{myForm.value | json}}
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <div formArrayName="arr" *ngFor="let a of myForm.get('arr').controls; let i = index">
    <div [formGroupName]="i" style="margin-bottom: 10px;">
      <input type="text" name="name" formControlName="name">
      <label for="pay">Pay:</label>
      <input type="text" name="pay" formControlName="pay">
      <div [formArrayName]="scores">
      <div  *ngFor="let _ of scores.controls; let g = index"> 
      <input type="text"  [formControlName]="g">
    </div></div></div></div>
  <button type="submit">Submit</button>
</form>

Name and pay are properly returned.

Error reported is

ERROR
Error: Cannot find control with path: 'arr -> 0 -> '
ERROR
Error: Cannot read properties of undefined (reading 'controls')

Solution

  • You can try below html:

    <form [formGroup]="myForm" (ngSubmit)="onSubmit()">
      <div formArrayName="arr" *ngFor="let a of arr.controls; let i = index">  <!-- arr getter is called -->
        <div [formGroupName]="i" style="margin-bottom: 10px;">
          <input type="text" name="name" formControlName="name">
          <label for="pay">Pay:</label>
          <input type="text" name="pay" formControlName="pay">
          <div formArrayName="scores"> <!-- Property binding is not required  -->
          <div  *ngFor="let _ of scores(i).controls; let g = index"> <!-- inner FormArray is retrieved based on index -->
          <input type="text"  [formControlName]="g">
        </div></div></div></div>
      <button type="submit">Submit</button>
    </form>
    

    and define appropriate getter and method to get hold of the FormArray as:

    // returns the outer FormArray
    get arr(): FormArray {
      return this.myForm.get('arr') as FormArray;
    }
    
    // returns the inner FormArray based on the index 
    scores(index: number): FormArray {
      return this.arr.at(index).get('scores') as FormArray;
    }