Angular Deeply Nested Reactive Form: Cannot find control with path on nested FormArray

Jeremy Lucas

I am building a nested, dynamic Form where the User has a group, and then can nest conditions within that group, or new additional group objects within a group FormArray. Here is what the basic UI looks like. Note, not all the pieces are working, but for now I am trying to add a nested group. A nested group will work for the FormBuilder, but it gives an error and does not show correctly on the UI. The error is: ERROR Error: Cannot find control with path: 'statement -> groups -> 0 -> groups -> conditions' . Before going further, the StackBlitz can be found HERE

enter image description here

The form object looks like this:

{
  "statement": {
    "groups": [
      {
        "conjunctor": null,
        "conditions": [
          {
            "variable": ""
          }
        ],
        "groups": []
      }
    ]
  }
}

Within the statement → groups → groups the user is able to push an additional FormGroup that will contain a "groups" object:

 {
 "conjunctor": null,
   "conditions": [
     {
       "variable": ""
     }
    ],
   "groups": []
 }

Long term, I expect to be able to push additional groups and further nest this Form, but for now, I am trying to get it to work on the UI. The HTML is as shown below and in this StackBlitz. I continue to get the error: ERROR Error: Cannot find control with path: 'statement -> groups -> 0 -> groups -> conditions' , and based off several S.O. examples, I recognize that this error is due to the way my HTML is nested and the FormGroups and FormArrays, there must be an issue within it. However, I cannot seem to get it to work in order to nest and display a nested group. Here are some approaches I have tried:

Angular FormArray: Cannot find control with path

Angular: Cannot find control with path: 'variable-> 0 -> id'

Angular 7 and form arrays error of cannot find a control with path

ERROR Error: Cannot find control with path

As a side-note, I'm not sure if this is even the best approach to implementing a nested reusable component, but I expect to research this further once I stop getting errors.

<form [formGroup]="form">
  <div formArrayName="statement">
    <div formArrayName="groups">
      <div *ngFor="let group of form.get('statement.groups')['controls']; let i = index">
        <fieldset>
          <legend>Group {{ i + 1 }}:</legend>
          <div [formGroupName]="i">
            <span style="float: right;">
              <button type="button" style="float: right; cursor: pointer; margin-left: 5px;" (click)="deleteGroup(i)">
                delete group
              </button>
              <button type="button" style="cursor: pointer; margin-left: 5px;" (click)="addNestedGroup(i)">
                add nested group
              </button>
              <button
                type="button"
                style="cursor: pointer; margin-left: 5px;"
                (click)="addNewCondition(group.controls.conditions)"
              >
                add condition
              </button>
            </span>
            <div formArrayName="conditions">
              <div *ngFor="let condition of group.get('conditions')['controls']; let j = index">
                <fieldset>
                  <legend>Condition {{ j + 1 }}</legend>
                  <div [formGroupName]="j">
                    <input style="vertical-align: middle;" type="text" formControlName="variable" />
                    <button
                      style="float: right; margin-bottom: 5px;"
                      (click)="deleteCondition(group.controls.conditions, j)"
                    >
                      delete condition
                    </button>
                  </div>
                </fieldset>
              </div>
            </div>
            <ng-container>
              <div formArrayName="groups">
                <div *ngFor="let num of group.get('groups').value; let idx = index">
                  <fieldset>
                    <legend>Group {{ 2 }}:</legend>
                    <span style="float: right;">
                      <button
                        type="button"
                        style="float: right; cursor: pointer; margin-left: 5px;"
                        (click)="deleteGroup(0)"
                      >
                        delete group
                      </button>
                      <button type="button" style="cursor: pointer; margin-left: 5px;" (click)="addNestedGroup(0)">
                        add nested group
                      </button>
                      <button
                        type="button"
                        style="cursor: pointer; margin-left: 5px;"
                        (click)="addNewCondition(num.conditions)"
                      >
                        add condition
                      </button>
                    </span>
                    <div formArrayName="conditions">
                      <div *ngFor="cond; of: group.controls; let k = index">
                        <fieldset>
                          <legend>Condition {{ k + 1 }}</legend>
                          <div [formGroupName]="k">
                            <input style="vertical-align: middle;" type="text" formControlName="variable" />
                            <button
                              style="float: right; margin-bottom: 5px;"
                              (click)="deleteCondition(group.controls.conditions, k)"
                            >
                              delete condition
                            </button>
                          </div>
                        </fieldset>
                      </div>
                    </div>
                  </fieldset>
                </div>
              </div>
            </ng-container>
          </div>
        </fieldset>
      </div>
    </div>
  </div>
</form>
julianobrasil

I've written a post at dev.to after writing this answer. Take a look.


You're dealing with a complex form. It's nested and it's recursive (as you have groups in groups). I suggest you split it into more components. By doing that, you'll make it easier to have a big picture of the whole form whenever you revisit it for any reason. And, as a very welcome cherry-on-the-cake, you will avoid the deeply nested object paths you're using to access your controls (this can be overwhelming as you keep nesting dynamic forms the way you're doing).

What I'm trying to say is that the error is likely caused by some silly mistake in the deep object paths you use to get access to the form parts. When dealing with this kind of complex nested form, it usually isn't worth the effort to fix eventual issues related to wrong object paths: refactor it to get a more clean-structured component.

I strongly suggest you do the two things I'll describe below (also, take a look at this Stackblitz demo). What I did in that demo is a complete refactor of your form and I decided not to paste all the code here because it would be excessively long, hard to read, and you wouldn't be able to execute it anyway. So it would be pointless. Just go to the Stackblitz demo and try it there.

Your form has a very peculiar aspect: it's recursive. So everything is gonna be easier if we don't try to row the boat against its recursive nature stream.

I assure you I did nothing special in that code but just these two steps:

1 - Create a wrapper recursive form component:

Let's call it GroupFormComponent. The one thing that's not so common here is that, in the template of this component, you're gonna have... another GroupFormComponent. Yes, you can bury an angular component inside itself recursively.

@Component({
  selector: 'group-form',
  template: `
    ...
    <!-- here you nest another instance of this component -->
    <group-form *ngIf="nestCondition"></group-form>
    ...
  `,
})
export class GroupFormComponent {...}

The above snippet helps to illustrate what I'm suggesting you do (this kind of structure shows how far you can go with angular component-based nature => it's powerful, isn't it?).

2 - Split your form into more controls

You can (and should) group some parts of your form into other components, to make it easier to be understood as a whole. Without any great mental effort, we can identify three components:

  • The main form, containing the overall form

  • A bar of action buttons

  • A condition component

When you assemble all these parts together, you'll get:

<main-form>
  <action-buttons></action-buttons>
  <condition></condition>
  <condition></condition>
  ...
  <condition></condition>

  <!-- The recursive part -->
  <main-form></main-form>
  <main-form></main-form>
  ...
  <main-form></main-form>
</main-form>

To make it even more simple, <condition> and <main-form> components must implement the ControlValueAccessor interface in order to allow them to be used as FormControl's in other forms.

With all these this in place, you'll have a robust, maintainable, and flexible form.

The animated gif below shows it working.

enter image description here

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

angular 4: nested form fields : Cannot find control with path

Angular FormArray: Cannot find control with path

Angular formArray Cannot find control with path

Nested angular reactive form and error with finding control

FormArray with nested group of controls in Reactive Form with Angular 5

Angular Dynamic Reactive Form Nested FormArray for Radios Buttons

Angular Reactive Forms: Cannot find control with path:

Patch Value to FormArray Nested within FormArray of FormArray in Angular reactive Forms

Angular Reactive Forms with nested formGroups inside a formArray

Angular Reactive Form nested Form

Angular 5 FormArray > Cannot find control with path: 'fields -> 0 -> name'

ERROR Error: Cannot find control with path: Angular FormArray

Angular2: Cannot find form control at index 1 at FormArray

Nested FormArray Reactive Forms

Angular Reactive Form: Using a FormArray and adjusting the FormControls leads to Error There is no form control element for path

Add Nested Reactive FormArray within FormArray - Angular 6

Angular 4 reactive form - FormArray Within FormArray unable to get path

Angular Form Array Cannot find control with path

Angular 2 Form "Cannot find control with path"

Angular reactive form with nested array

Nested Form Array Woes: ERROR Error: Cannot find control with path: 'questions -> 0 -> code'

Angular 2 Reactive Forms: Cannot find control with path

Cannot find control with name: formControlName in angular reactive form

Deeply Nested resources Form

Model Driven Form Nested FormArray Control in a FormGroup control

Building form from json with repeatable inputs: Cannot find control with path formArray

How to update the nested object in Angular reactive form

Null value in Angular Reactive form nested FormGroup

Angular 6 nested reactive form component

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive