Your start is good, but you have to write your source code differently.
Instead of this example app.components.ts
is main component and my-array.component.ts
is child component.
Our test data
classFields1: any[] = ['firstname', 'lastname', 'email', 'password'];
classFields2: any[] = ['country', 'city', 'street', 'zipcode'];
Step 1. Use FormBuilder for form creation (app.component.ts)
You must import FormBuilder
and FormGroup
from @angular/forms
like this:
import { FormBuilder, FormGroup } from '@angular/forms';
and then define in constructor:
constructor(private formBuilder: FormBuilder) { }
Step 2. Define new empty FormGrooup
Now you can define new empty FormGroup in ngOnInit
like this:
ngOnInit() {
this.myForm = this.formBuilder.group({});
}
Step 3. Create FormControls dynamically (app.component.ts)
Now you can start with dynamically creation of your FormControls
by iteration of classFields
. For this I would recommend to create own function. This function gets two parameter: arrayName
and classFields
. With arrayName
we can set custom name of our FormArray
-control. classFields
-Array we will use for iteration. We create constant variable for empty FormArray
, which we called arrayControls
. After this we iterate over classFields
and create for each element FormControl
, which we called control
, and push this control
into arrayControls
. At the end of this function we add our arrayControls
to our Form with custom name by using arrayName
. Here is an example:
createDynamicArrayControls(arrayName: string, classFields: any[]) {
const defaultValue = null;
const arrayControls: FormArray = this.formBuilder.array([]);
classFields.forEach(classField => {
const control = this.formBuilder.control(defaultValue, Validators.required);
arrayControls.push(control);
})
this.myForm.addControl(arrayName, arrayControls);
}
Import FormControl
and FormArray
from @angular/forms
. Your import line should be like this:
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';
Now call createDynamicFormControls
-Function in ngOnInit
.
Step 4. HTML Template for this dynamic Form (app.component.html)
For this example I create following template:
<h1>My Form</h1>
<form [formGroup]="myForm">
<div formGroupName="test1">
<app-my-array [classFields]="classFields1" [arrayFormName]="myForm.controls.test1"></app-my-array>
</div>
<div formGroupName="test2">
<app-my-array [classFields]="classFields2" [arrayFormName]="myForm.controls.test2"></app-my-array>
</div>
<button type="button" (click)="saveForm()">Submit</button>
</form>
Here we have new div element with formGroupName
. This group name is our arrayName
in our form. We give our form arrays via @Input
to my-array.component
.
Step 5. MyArrayComponent
Now this component is very simnple:
import { Component, OnInit, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-my-array',
templateUrl: './my-array.component.html',
styleUrls: ['./my-array.component.css']
})
export class MyArrayComponent implements OnInit {
@Input() classFields: any[];
@Input() arrayFormName: FormGroup;
constructor() { }
ngOnInit() { }
}
Here we have only two @Input
varibales. (I know, this variable can have a better names :-) ).
Step 6. HTML for MyArrayComponent
<div [formGroup]="arrayFormName">
<div *ngFor="let class of arrayFormName.controls; let index = index;">
<label [for]="classFields[index]">{{ classFields[index] }}</label>
<input type="text" [id]="classFields[index]" [formControlName]="index" />
</div>
</div>
<br>
And here is working example on Stackblitz: https://stackblitz.com/edit/angular-wawsja
If you have some question ask me in comments or read the Angular documentation abour Reactive Forms here.