2

Here is the problem:

I have a complex form with nested formgroups, here is a "simplified" structure of what it looks like :

-> MyForm (formGroup)
    -> Whatever01 (formControl - input)
    -> Whatever02 (formControl - input)
    -> WhateverGroup01 (formGroup)
        -> Whatever03 (formControl - input)
        -> Whatever04 (formControl - input)
    -> WhateverArray01 (formArray)
        -> WhateverGroup02 (formGroup)
            -> Whatever05 (formControl - input)
            -> WhateverGroup03 (formGroup)
                -> Whatever06 (formControl - input)
        -> WhateverGroup04 (formGroup)
            -> Whatever07 (formControl - input)
    -> ...

Angular side, it should look somehow like this (not correct/complete, but just to give an idea) :

this.myForm = this.fb.group({
    whatever01: ['',Validators.compose([...])],
    whatever02: ['',Validators.compose([...])],
    whateverGroup01: this._formBuilder.group({
        whatever03: ['',Validators.compose([...])],
        whatever04: ['',Validators.compose([...])]
    }),
    whateverArray01: this._formBuilder.array([
        this._formBuilder.group({
            whatever05: ['',Validators.compose([...])],
            whateverGroup03: this._formBuilder.group({
                whatever06: ['',Validators.compose([...])]
            })
        }),
        this._formBuilder.group({
            whatever07: ['',Validators.compose([...])],
        })
    ])
    ...
});

Things go pretty fine from root myForm item to fetching the formArray, but then come the troubles....

So, I just can't access "whatever05" (and 06 but 05 does NOT work... so...) formControl to bind it to the template ! Here is what the template actually looks like (intentionnaly skipped the part before the array), the interesting part is the [????]="????", this is the problem actually.

<form [formGroup]="myForm" ...>
    <!-- ...skipped... -->
    <div formArrayName="whateverArray01" *ngFor="let item of myForm.controls.whateverGroup01.controls.whateverArray01.controls;let idx = index;" [formGroupName]="idx">
        <div [????]="????">
            <input formControlName="whatever05" ... />
            <div [????]="????">
                <input formControlName="whatever06" ... />
            </div>
        </div>    
    </div>
</form>

The formGroups located in the formArray have all the same structure.

Basically, the problem is that I canNOT access the formControls within the formGroups...

I tried several solutions, I used [formGroupName] , formGroupName (without brackets), [formGroup], formControlName, ... But cannot figure out what I have to use to be able to bind the corresponding formGroup/formControl with the data !

I come to this kind of errors by now :

formGroup expects a FormGroup instance. Please pass one in. 
// This when using [formGroup]="item.whateverGroup02"

Cannot find control with name: 'whatever05'
// When using [formGroup]="item.controls.whateverGroup02"

Cannot find control with path: 'whateverArray01 -> 0 ->'
// This when using [formGroupName]="whateverGroup02"

Thanks for reading / help

Here is a plunker with some code :

http://plnkr.co/edit/wf7fcHMkhIwzmLWLnCF8?p=preview

8
  • formArrayName needs to be in a wrapping element for formGroupName. Commented Apr 20, 2017 at 17:36
  • Also this beast right here myForm.controls.whateverGroup01.controls.whateverArray01.controls can be condensed to myForm.get('whateverGroup.whateverArray'). Commented Apr 20, 2017 at 17:39
  • Also I think FormArray needs to have identical nested FormGroups. Commented Apr 20, 2017 at 17:41
  • Hi! Thanks for comments, My formGroups inside formArray all have the same structure. This will not be a problem. I dont understand what you mean in your first comment... Commented Apr 20, 2017 at 18:06
  • It's not the same in your example above. I mean that you are declaring formArrayName and formGroupName in the same element. Move formArrayName to a higher up element. Commented Apr 20, 2017 at 18:11

2 Answers 2

2

The build of your form seems correct to me. You have some trouble in your template, the iteration of your FormArray is incorrect, your FormArray is not inside the FormGroup WhateverGroup01, so the iteration should look like this:

*ngFor="let ctrl of myForm.controls.whateverArray01.controls;

As to the template part of your FormArray, it should look like this:

<div *ngFor="let ctrl of myForm.controls.whateverArray01.controls; let i = index" [formGroupName]="i">
   <input formControlName="whatever05" />
   <div formGroupName="whateverGroup03">
      <input formControlName="whatever06" />
   </div>
</div>

That should solve the issue :)

Here's a

Demo

Sign up to request clarification or add additional context in comments.

1 Comment

Well, this is a good point, but this does not exactly solve my issue. I don't have this nested issue. But you're right about it, its a mistake from my copy... I updated the question with a "non-working" plunker. Thanks :)
2

First of all your view has wrong binding:

[formGroupName]="whateverGroup02"

There is no whateverGroup02 property in your component. We should pass string as follows:

formGroupName="whateverGroup02"

Then if you build group like:

this.fb.group({
  x: 1,
  y: {
    z: 2
  }
})

you will get

FormGroup
  -> FormControl with name `x` and value `1`   
  -> FormControl with name `y` and value `{ z: 2 }`

It means if you want to manipulate nested formGroups you have to create their. i.e.

let fGroups = data.map(rs => this.buildFormGroup(rs));
...
buildFormGroup(obj) {
  let formGroup: { [id: string]: AbstractControl; } = {};
  Object.keys(obj).forEach(key => {
    formGroup[key] = typeof obj[key] === 'object' ?
      this.buildFormGroup(obj[key]) : 
      new FormControl(obj[key]);
  });
  return this._formBuilder.group(formGroup);
}

Plunker Example

1 Comment

Hi there! Thanks for your reply! Checked the example, this actually solves the problem for the formGroup, but what if there were also nested formArrays? Should I add a "buildFormArray" function or something? Thx

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.