angularnested-forms

Cannot read property 'addControl' of null


Nested form, trying to add one form inside other but getting error 'Cannot read property 'addControl' of null'. FormGroupDirective not returning parent 'form' it seems. Trying to apply Sub-Forms approach for nesting.

    <p>
      sub-forms-approach works!
    </p>
    <form [formGroup]="form">
      <!--<input formControlName="name">-->
      <app-sub-forms-approach-child-one></app-sub-forms-approach-child-one>

    </form>  
    state: {{form.status}}
    data:  {{ form.value | json}}

Parent Component

    import { Component, OnInit } from '@angular/core';
    import {FormBuilder, FormControl, FormGroup, Validators} from 
    '@angular/forms';

    @Component({
      selector: 'app-sub-forms-approach',
      templateUrl: './sub-forms-approach.component.html',
      styleUrls: ['./sub-forms-approach.component.css']
    })
    export class SubFormsApproachComponent implements OnInit {
    form= new FormGroup({

        });
      constructor() { 
      }
      ngOnInit() {
      }

    }

Child Form HTML

sub-forms-approach-child-one works!

    <div formGroupName='address'>
      <input formControlName="pin">
      <input formControlName="street">
    </div>

Child Form Component

    import { Component, OnInit } from '@angular/core';
    import { ControlContainer, FormGroupDirective, FormControl, FormGroup} 
     from '@angular/forms';
    @Component({
      selector: 'app-sub-forms-approach-child-one',
      templateUrl: './sub-forms-approach-child-one.component.html',
      styleUrls: ['./sub-forms-approach-child-one.component.css'],
      viewProviders: [
        {provide: ControlContainer,
          useExisting: FormGroupDirective 
        }
      ]
    })
    export class SubFormsApproachChildOneComponent implements OnInit {
      form;
      constructor(parent: FormGroupDirective) { 
        this.form = parent.form;
        console.log(parent.form);
      }

      ngOnInit() {
        this.form.addControl('address', new FormGroup({
          pin: new FormControl(),
          street: new FormControl()
        }))
      }

    }

Solution

  • You can't get FormGroupDirective.form in constructor because @Input form property is not initialized yet. Angular firstly instantiates component classes during node creation and only after that initializes input properties.

    So move your code to ngOnInit hook:

    constructor(private parent: FormGroupDirective) {}
    
    ngOnInit() {
      this.form = this.parent.form;
      this.form.addControl('address', new FormGroup({
        pin: new FormControl(),
        street: new FormControl()
      }))
    }
    

    Ng-run Example