In my app I construct formGroups
dynamically from a config object that looks like this:
const formElements: FormElementInterface[] = [
{
type: 'formControl',
defaultIsArray: false,
defaultValue: 'Apfel',
formControlName: 'fruits',
htmlTag: 'mat-input',
inputIype: 'text'
} as InputFormControlInterface,
];
The FormElementInterface[]
consists either of formControl
objects or formGroup
objects. The latter can contain formControls
or more formGroups
.
Constructing the actual formGroup
, which is called completeForm
as you will see in the template, went smoothly, but inside the template I met some problem and got this error:
formControlName must be used with a parent formGroup directive. You'll want to add a formGroup directive and pass it an existing FormGroup instance (you can create one in your class)
This is an excerpt from my template:
<form [formGroup]="completeForm">
<div *ngFor="let formElement of forms">
<ng-container
*ngTemplateOutlet="formElement.type === 'formGroup' ? formGroup : formControl; context:{$implicit: formElement}">
</ng-container>
</div>
</form>
<ng-template #formControl let-formElement>
<span [ngSwitch]="formElement.htmlTag">
<div *ngSwitchCase="'mat-input'">
<mat-form-field class="example-full-width">
<input matInput [value]="formElement.defaultValue" formControlName="fruits">
</mat-form-field>
</div>
</span>
</ng-template>
As you can see formGroup
is set. Are the ng-template
interfering?
I found the solution: due to the ng-template
formControlName
isnt sufficient since ng-template
kinda messes up the hierarchy in the template. Therefore the path to the formControl
inside the formGroup
must be provided like so:
<input matInput [value]="formElement.defaultValue" [formControl]="getFormControl(formElement.formControlName)">