I trying to learn to create generic template for form where in passing json, would define the structure for the table rendered.
I am unable to add controls and form array to the fromGroup programmatically without declaring it earlier
https://stackblitz.com/edit/stackblitz-starters-ksvegt?file=src%2Fmain.ts
here is the code, please help me with this issue, and is it the right approach to do it
NOT use setControl else addControl
createForm(jsonData: JsonForm) {
this.form1.addControl('header', new FormControl(jsonData.header));
const controlArray = this.fb.array([]);
for (let control of jsonData.controls || []) {
controlArray.push(this.fb.control(control.value));
}
this.form1.addControl('controls', controlArray);
}
Always you have a fromArray use a getter to "reach" it and iterate over it
get controls()
{
return this.form1.get('controls') as any as FormArray
}
And you use
<form [formGroup]="form1">
<div
formArrayName="controls"
*ngFor="let control of controls.controls; let i = index"
>
<input [formControlName]="i" />
</div>
</form>
Your forked stackblitz
Well, this solve your code, but I feel that the way to create a formGroup is really create a formGroup, not a formArray
In this way the value of your formGroup have the structure of your json data
For this, I add a new property to your JsonFormControls interface, name
, that it's the name of the property
createForm(jsonData: JsonForm) {
//to iterate over an array use forEach instead a for
(jsonData.controls || []).forEach((control:JsonFormControls,index:number)=>{
this.form1.addControl(control.name ||'ctrl'+index,
new FormControl(control.value))
})
}
Well, now "how iterate"?
It's not a good idea iterate over jsonData.controls else you can iterate over form.controls using keyvaluePipe
<ng-template #DEFAULT_FORM_TITILE let-form="form1">
<h2>{{ jsonData.header }}</h2>
<form [formGroup]="form1">
<!-see you iterate over form1.controls|keyvalue
you use let i=index, to get the value of the jsonData.controls[i]
-->
<div *ngFor="let control of form1.controls|keyvalue;let i=index">
<!--sorry the "!", it's to avoid errors of "object can be undefined"-->
<label>{{jsonData!.controls![i].label}}
<input [type]="jsonData!.controls![i]?.type || null"
[formControlName]="jsonData!.controls![i]?.name || null" />
</label>
</div>
</form>
<!--just for check-->
<pre>
{{form1.value|json}}
</pre>
</ng-template>