How to use formGroupName inside child components

Livnat Menashe picture Livnat Menashe · Dec 3, 2018 · Viewed 7.8k times · Source

How do i use formGroupName inside child components? for example:

i have ParentFormComponent

    parentForm: FormGroup;
    constructor(private fb: FormBuilder, private http: Http) { }
    ngOnInit() {


 this.parentForm = this.fb.group({
        _general: this.fb.group ({
           ProjectName:''
       })
  })
 }

In the html:

  <form [formGroup]="parentForm" (ngSubmit)="submitForm()">
     <div formGroupName="_general">
        <mat-form-field>
             <input matInput placeholder="Project name" 
             formControlName="ProjectName">
        </mat-form-field>
    </div> 
  </form> 

it's working great but when i want to use child component it's not working:

<form [formGroup]="parentForm" (ngSubmit)="submitForm()">
          <app-child [parentForm]='parentForm'></app-child>
      </form> 

when i insert it to the child component:

<div formGroupName="_general">
            <mat-form-field>
                 <input matInput placeholder="Project name" 
                 formControlName="ProjectName">
            </mat-form-field>
        </div> 

and in the ts file

 @Input() parentForm:FormGroup;

i"m getting error: formGroupName 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).

Answer

Chellappan வ picture Chellappan வ · Dec 3, 2018

Instead of Using input property binding Use FormGroupDirective

FormGroupDirective

This directive accepts an existing FormGroup instance. It will then use this FormGroup instance to match any child FormControl, FormGroup, and FormArray instances to child FormControlName, FormGroupName, and FormArrayName directives.

Use Viewproviders to provide controlContainer, Inject FormGroupDirective in your child component to get the parentform instance

app.parent.html

<form [formGroup]="parentForm">
  <app-child></app-child>
</form>

child.component.ts

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, ControlContainer, FormGroupDirective, Validators, FormBuilder, NgModel } from '@angular/forms';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
  viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class ChildComponent implements OnInit {
  childForm;
  constructor(private parentF: FormGroupDirective) { }

  ngOnInit() {

    this.childForm = this.parentF.form;
    this.childForm.addControl('_general', new FormGroup({
      ProjectName: new FormControl('')
    }))

  }
}

child.component.html

<div formGroupName="_general">
     <mat-form-field>
                 <input matInput placeholder="Project name" 
                 formControlName="ProjectName"> 
      <mat-form-field>  
 </div>

Example:https://stackblitz.com/edit/angular-ezqupz