1

I'm trying to build a nested reactive form with formArray, but i get error: 'Cannot find control with path', it works fine if there is only one item in array, but if there is more that 1 it returns error. what am i doing wrong?

carPartCategories in ngfor is just data i get from server.

    <form [formGroup]="updateEstimation">
      <ng-container formArrayName="carPartStatus">
        <ng-container *ngFor="let i of carPartCategories; let j = index;">
            <ng-container [formGroupName]="j">
              <div class="content-desc mt-4 mb-5">
                <div class="row mt-4 parts-row align-items-center">
                  <div class="col-lg-2">
                    <span class="p-2 nusx">
                      {{i.carPartCategory}}
                    </span>
                  </div>
                  <div class="col-lg-3">
                    <span class="p-2 nusx">
                      {{i.carPartSubCategory}}
                    </span>
                  </div>
                  <div class="col-lg-2">
                    <span class="p-2 nusx">
                      <mat-form-field appearance="fill">
                        <mat-label>choose</mat-label>
                        <mat-select formControlName="status">
                          <mat-option>
                            test
                          </mat-option>
                        </mat-select>
                      </mat-form-field>
                    </span>
                  </div>
                  <div class="col-lg-2">
                    <span class="p-2 nusx">
                      X{{i.quantity}}
                    </span>
                  </div>
                  <div class="col-lg-2 price">
                    <input type="text" placeholder="price" class="form-control" formControlName="price">
                  </div>
                </div>
              </div>
              <div class="comment mt-4 mb-5" *ngIf="i.comment">
                <p class="mtav">comment</p>
                <p class="nusx">{{i.comment}}</p>
              </div>
              <hr>
            </ng-container>
          </ng-container>
        </ng-container>
       </form>

.ts

      this.updateEstimation = this.fb.group({
        carPartStatus: new FormArray([
          new FormGroup({
            status: new FormControl(''),
            price: new FormControl('')
          })
        ])
      });

StackBlitz: https://stackblitz.com/edit/angular-10-material-reactive-form-starter-bc7hd4?file=src/app/app.component.ts

2
  • Can you post a full example in CodeSandbox or something similar? Commented Mar 3, 2022 at 22:31
  • hi thanks for the comment! yes i can stackblitz.com/edit/… Commented Mar 4, 2022 at 8:41

1 Answer 1

2

That's happening because you added only one item under the FormArray, and looped through another array carPartCategories to render the items.

For each item in the carPartCategories array, the FormArray of carPartStatus should contain an item as a FormGroup, and keep the FormArray always synced with your original array by adding/removing the controls to it.

You can try something like the following:

// prop represents the `carPartStatus` control
carPartStatusCtrl: FormArray;

//...


this.carPartStatusCtrl = this.createFormArray(carPartCategories);

this.updateEstimation = this.fb.group({
  carPartStatus: this.carPartStatusCtrl,
});

// ...

// Create a `FormArray` from the provided array:
createFormArray(origin: CarPartCategories[]) {
  return new FormArray(
    origin.map(
      (item) =>
        new FormGroup({
          status: new FormControl(item.status),
          price: new FormControl(item.price),
        })
    )
  );
}

Each change on the original array should be reflected into the FormArray, for example, if you add a new item to the original array, a new item should be added to the FormArray like the following:

appendNewItem(item: CarPartCategories): void {
  this.carPartStatusCtrl.push(
    new FormGroup({
      status: new FormControl(item.status),
      price: new FormControl(item.price),
    })
  );
}

Update

Based on your StackBlitz, you're receiving the original array from the HTTP request, but you initialized the updateEstimation form-group without waiting the result to return, so your FromArray in this case won't contain any items since the carPartCategories is still empty.

To resolve this issue, you have to:

  • Either move the updateEstimation initialization to be within the subscribe function (and DON'T render the template until the updateEstimation is being initialized, by using *ngIf="updateEstimation" on the form element).
  • Or append the new items to the carPartStatusCtrl form-array, once the data is received using the appendNewItem function I mentioned above in my solution.
Sign up to request clarification or add additional context in comments.

4 Comments

hi! thank you so much for answer. i have one more question, you are code does work fine with simple array i tested, but in my project i have http request and it wont work. i made a stackblitz stackblitz.com/edit/…
I updated my answer to resolve the issue in your StackBlitz.
Hi! thanks again. when move updateEstimation inside subscribe i get error Error: formGroup expects a FormGroup instance. Please pass one in. for the second solution i dont get it, can you explain it please?
Regarding the second solution, I updated it to be more clear, and the same for the first one. The *ngIf="updateEstimation" should be added on form element to render the form only once the updateEstimation is initialized.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.