Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular2 - validating FormControlName in child component of parent FormGroup

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.

like image 389
user2850751 Avatar asked Dec 23 '22 23:12

user2850751


2 Answers

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

like image 192
silentsod Avatar answered Dec 28 '22 09:12

silentsod


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

like image 42
alpham8 Avatar answered Dec 28 '22 11:12

alpham8