Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more

we recently upgraded from ng 7.2.15 and typescript 3.2.4 to angular v8.2.14 and typescript v3.5.3. Passing the form group from a parent component to child component is no longer working.

Below is my child component: child component. ts

@Component({selector:'edit-overview'})
    export class ChildComponent implements OnInit {  
       public OverviewFormGroup : FormGroup
       constructor(private controlContainer: ControlContainer) {
       }

    ngOnInit() {
    this.OverviewFormGroup = <FormGroup>this.controlContainer.control;
    }
    }

child.component.html

<div [formGroup] ='OverviewFormGroup'>
</div>

and my parent component

Parent.component.html

<div [formGroup]="Form1">
      <edit-overview [formGroup] = "Form1.controls.OverviewFormGroup">
      </edit-overview>
</div>

Parent.component.ts

export class ParentComponent {
constructor(private readonly fb: FormBuilder) {
this.Form1 = this.fb.group({
 name: new FormControl('', [Validators.required]),
 OverviewFormGroup: new FormGroup({
        description: new FormControl('', [Validators.nullValidator])
      })
})
}
}

It throws this error: Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more at the parent template line.

Earlier passing a formgroup from parent to child was no longer an issue. Am i missing something here? I have already given value for controls in the Form group declaration.

like image 318
Priyanka Avatar asked Dec 11 '19 11:12

Priyanka


1 Answers

Good question, it is an obscure error. The error comes from typesafety features! Because Angular cannot know that it is a form group from the way you're accessing it (it just knows it is an AbstractFormControl), you need to tell it!

Option 1: Use as to make the type explicit

So for example if you have:

  mainForm: FormGroup = this.formBuilder.group({
    name: ['Max'],
    address: this.formBuilder.group({
      street: ['PayneStreet'],
      zip: [50000]
    })
  });

In order to let Angular know that you're actually accessing a form control, you need to tell it:

  get addressForm() {
    return this.mainForm.get('address') as FormGroup;
  }

The important part is the as FormGroup. Like this Angular knows that it's actually a FormGroup and not just an abstract form control. Then you can go ahead and use it in the html:

<app-address-form [addressForm]="addressForm"></app-address-form>

Find the stackblitz here: https://stackblitz.com/edit/angular-nested-forms-input

Option 2 (preferred): Define the nested group separately

It is actually easier and more typesafe to just build the second form separately and then to attach it to the main form:

  addressForm = this.formBuilder.group({
    street: ["PayneStreet"],
    zip: [50000]
  });

  mainForm: FormGroup = this.formBuilder.group({
    name: ["Max"],
    address: this.addressForm
  });

and in the html (same as above)

  <app-address-form [addressForm]="addressForm"></app-address-form>

Like this, Angular knows already that addressForm is of type FormGroup and not just of type AbstractFormControl

Stackblitz: https://stackblitz.com/edit/angular-nested-forms-input-2

like image 144
bersling Avatar answered Dec 21 '22 06:12

bersling