I have an angular component corresponding a form/page that is generating an indeterminate amount of child components, each representing an individual field, and I would like the parent component's FormGroup to validate the fields contained in the child components. Only when I do so, I get an error:
A FormControlName must have a corresponding FormGroup.
Here is the template code for my parent component:
<div class="form-group" [formGroup]="parentGroup">
<table>
<tbody>
<tr *ngFor="let i of array">
<child [property]="i" [options]="myForm.controls[i.id]"></child>
</tr>
</tbody>
</table>
</div>
The form is defined in the component file here. I'm adding the FormControls according to how many child components we're adding:
private formAttrs: FormGroup;
constructor(private _fb: FormBuilder) { }
ngOnInit() {
this.myForm = this._fb.group({});
for (var i = 0; i < this.array.length; i++) {
this.formAttrs.addControl(this.array[i].id, new FormControl(this.array[i].value, Validators.required));
}
}
The template code for the child component is this:
<td class="prompt">
{{i.label}}
</td>
<td class="required" width="1%">
<span *ngIf="property.required">*</span>
</td>
<td>
<input type="text " class="form-control" [ngClass]="{error: !options.valid}" formControlName="property.id">
</td>
<td>
While there is nothing defined in the child component class (other than the "property" and the FormControl element passed down for "options"), I would think that the formGroup in the parent component would be able to match with the formControlName in the child component, but instead I get the error:
EXCEPTION: Error in ./ChildComponent class ChildComponent - inline
template:7:109 caused by: 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).
Is there a way I can get around this error? If not, is there another solution to this problem that someone can suggest?
Thanks in advance.
There are a couple of things I came across implementing this in a Plunker.
First, we'll need to pass in our formGroup from the parent to the child so we have a FormGroup to satisfy the templating engine's enforcement of FormControls being a part of a FormGroup:
child.component.ts
@Input() parentGroup: FormGroup;
child.component.html
<td [formGroup]="parentGroup">
<...>
</td>
Then we'll also need to set the [formControl]
or evaluate property.id
, otherwise it looks for the name "property.id":
<input type="text " class="form-control" [ngClass]="{error: !options.valid}" [formControl]="options"/>
or
<input type="text " class="form-control" [ngClass]="{error: !options.valid}" formControlName="{{property.id}}"/>
Your code was using different variables binding the formGroup
and using formAttrs
which was a little unclear as to what was going on so I went ahead and collapsed them to one and you can see that in the Plunker: http://plnkr.co/edit/3MRiO9bGNFAkN2HNN7wg?p=preview
The problem here is, that it is not possible to have the same form control name multiple times in one form group.
You need to declare an own form group for each child component and then you can iterate over it in the parent component based on your reference attribute. You can get each child form control with the directive component method FormGroupDirective.getControl(controlName)
as you can see in documentation: https://angular.io/docs/ts/latest/api/forms/index/FormGroupDirective-directive.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With