stackblitz
public myForm: FormGroup;
ngOnInit() {
this.myForm = new FormGroup({});
for(let item of ['item1', 'item2', 'item3']) {
this.myForm.addControl(item,
new FormGroup({
name: new FormControl(),
hobbyList: new FormArray([])
})
)
}
}
onAddHobby(group:FormGroup) {
(group.get('hobbyList') as FormArray).push(new FormControl())
}
hobbiesArray(group:FormGroup):FormArray
{
return group.get('hobbyList') as FormArray
}
The .html
<form [formGroup]="myForm">
<ng-container *ngFor="let group of myForm.controls |keyvalue">
<div style="margin:20px;" [formGroup]="group.value">
<label for="">{{group.key}}</label>
<input type="text" formControlName="name">
<button type="button" (click)="onAddHobby(group.value)">Add Hobbies</button>
<div formArrayName="hobbyList">
<div *ngFor="let item of hobbiesArray(group.value).controls; let i = index">
<label for="">Hobbies</label>
<input [formControlName]="i">
</div>
</div>
</div>
</ng-container>
</form>
<pre>
{{myForm?.value|json}}
</pre>
But let me explain a bit the code. You has a FormGroup with three FormGroup, each of them has a FormControl and a FormArray. I like iterate always over the form of over elements of the form, it's the reason to iterate over some "bizarro" like let group of myForm.controls |keyvalue under this div, group.value will be each FormGroup, and group.key will be the name of the propertie.
As is a FormGroup, we create a div with this [formGroup]
<div style="margin:20px;" [formGroup]="group.value">
...
</div>
Under this div, we ask about the formControl "name" using
<input type="text" formControlName="name">
And about the formArray like
<div formArrayName="hobbyList">
We has a function to get the formArray, hobbiesArray(group.value) that pass the FormGroup, identically in onAddHobby we pass the FormGrorup