I'm creating a project with a Reactive Form
; based on Recursive
Component that creates Dynamic Form
from JSON
file.
The Sources
This is an adaptation from Ionic based on Creating Dynamic Angular Forms with JSON
I Adapted the Recursive version procedures and other changes!
My code is located in Stackblitz.
I will show a reduced code version of json-form.component.html file:
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div fxLayout="column">
<ng-container *ngFor="let control of jsonFormData?.controls">
<div fxFlex="100%">
<selects
*ngIf="control.type === 'select'"
[control]="control"
[visible]="true"
></selects>
</div>
</ng-container>
</div>
<button mat-raised-button class="mt-1" color="primary">
<em class="fa fa-save">Submit</em>
</button>
</form>
As you can see the custom component is selects
.
Now, let's take a look at the Recursive
code of use of the selects
template. Again I reduce the code of select.component.html file:
<form [formGroup]="form">
<ng-container *ngIf="control?.children">
<mat-form-field
*ngIf="control.type === 'select' && control.visible"
fxFlex="100%"
hideRequiredMarker
>
<mat-label>{{ control.label }}</mat-label>
<mat-select
[formControlName]="control.name"
[placeholder]="control.label"
(selectionChange)="onSelectChange($event.value)"
>
<mat-option
*ngFor="let child of control.children"
[value]="child.value"
>
{{ child.label }}
</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
<ng-container *ngFor="let child of control?.children">
<div fxFlex="100%">
<selects *ngIf="child.type === 'select'" [control]="child"></selects>
</div>
</ng-container>
</form>
The code of recursion using selects
Component is:
<ng-container *ngFor="let child of control?.children">
<div fxFlex="100%">
<selects *ngIf="child.type === 'select'" [control]="child"></selects>
</div>
</ng-container>
An example of error is:
ERROR
Error: Cannot find control with name: 'Petitioner (C2 -> P2)'
Unfortunately, I can't to find the problem in order to solve it.
Some clue in order to solve the error?
EDIT I suspect that not all components are shown inmediately, only when the Select is clicked; then the component is not still created.
As you can see in the displayed view, all the
FormControl
are there. But, when a click event is presented. I show the allFormControl
's of myForm
in that istant with the line:console.log(this.form.value);
As you can see in the
Green
bottom right rectangle in. In the last Event. Only appears two controls!!!!, But are shown 7 formControls without button!... Then my Form (variablethis.form
) need to add those FormControl's.How to do that?
First, I need to obtain the main
Form
andFormGroup
(of my parent Component).In my parent component (
JsonFormComponent
) from the json-form.component.ts file:Now, I have
public
myForm
: FormGroup...
andpublic
myFormBuilder
: FormBuilder;
for my parent Component!.The next step, is create local variable in each child-component located in the selects.component.ts file.
Now, I have
public
form
: FormGroup...
and@Input()
formBuilder
: FormBuilder;
for my child Component!.The next step, is to pass that objects to my child-components:
The solution in order to pass (or relate)
myForm
(FormGroup
) comes from this post. But, the relation formyFormBuilder
is done in the json-form.component.html file.Specifically in the line:
[formBuilder]="myFormBuilder"
.And for the recursion, in the selects.component.html file
Specifically in the line:
[formBuilder]="formBuilder"
.Now, in my child-component in the file selects.component.ts I created this method:
Lastly: I changed my method, in order to add the
FormControl
that needs to be displayed:Note specifically the lines:
this.newControl(child);
andthis.newControl(sibling);
.As you can see in the
Blue
rectangle, the errors are gone.NOTE: Theres is not the only one solution, here a question How can I pass the FormGroup of a parent component to its child component using the current Form API about this subject.