Cannot create property 'validator' on string

tony09uk picture tony09uk · Jan 26, 2018 · Viewed 20.8k times · Source

I am trying to create an Angular 5 nested reactive form.

I started by creating a flat form, which worked as expected, but as soon as I extract part of my form and place it in as a child component I get an error

ERROR TypeError: Cannot create property 'validator' on string 'addressFormGroup'

If I just start typing another error is then displayed in the console

ERROR TypeError: this.form.get is not a function

What am I doing wrong? I've read several threads and tutorials to try and solve this, but I think i'm missing something obvious.

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

@Component({
moduleId: module.id,
selector: 'app-property-form',
templateUrl: './property-form.component.html',
styleUrls: ['./property-form.component.css']
})
export class PropertyFormComponent implements OnInit {

propertyForm: FormGroup;

constructor(private _formBuilder: FormBuilder) {}

ngOnInit() {
    this.createForm();
}

createForm() {
    this.propertyForm = this._formBuilder.group({
        saleOrLet: ['Sales', Validators.required],
        addressFormGroup: this.initAddress()
    })
}

initAddress() {
    return this._formBuilder.group({
        houseNameNumber: '',
        address2: '',
        postCode1: '',
        postCode2: ''
    })
}
}

Working form

<form [formGroup]="propertyForm" novalidate>
<fieldset>
<legend>Address</legend>
<div formGroupName="addressFormGroup">
  <div class="form-group">
    <label>
      House Name Or Number:
      <input placeholder="15 Nursery ave" formControlName="houseNameNumber">
    </label>
  </div>
  ...other inputs follow the same pattern...
</div>
</fieldset>
</form>

Broken form (when split in to parent child format)

Parent

<form [formGroup]="propertyForm" novalidate>
  <fieldset>
    <legend>Address 2</legend>
    <app-property-form-address group="addressFormGroup"></app-property-form-address>
  </fieldset>
</form>

Child

<div [formGroup]="group">
 <div class="form-group">
    <label>
      House Name Or Number:
      <input placeholder="15 Nursery ave" formControlName="houseNameNumber">
    </label>
  </div>
  ...other inputs follow the same pattern...
</div>

Child component

import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Component({
   selector: 'app-property-form-address',
   templateUrl: './property-form-address.component.html',
})
export class PropertyFormAddressComponent {
    @Input() group: FormGroup;
}

Answer

Nikola Jankovic picture Nikola Jankovic · Feb 15, 2018

You're passing the form group name as a string rather than a reference to the formGroup and trying to typecast it as a FormGroup (group="addressFormGroup"). group="addressFormGroup" doesn't pass the formGroup object, it passes a string with the value of addressFormGroup.