23
votes

I got a problem when reinitializing formGroup from parent component that is used in my custom component. Error that i get is:

There is no FormControl instance attached to form control element with name: 'selectedCompany'

HTML:

<form [formGroup]="addForm">
     ...
     <my-custom-component formControlName="selectedCompany"></my-custom-component>
     ...
</form

<my-custom-component> is created according to valid way of creating custom formControl component: https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html#implementing-controlvalueaccessor

Component

This is code that initializes formGroup variable addForm:

let formTemp: any = {
    selectedCompany: new FormControl(null, [Validators.required]),
}

this.addForm = this._formBuilder.group(formTemp);

First time addForm is initialized all is good. But when i reopen modal where form is located, and same component code is executed, above mentioned error occurs.

3

3 Answers

25
votes

I figured out that it is not good to reinitialize formGroup over and over again, because component looses reference to old formGroup.

If setting values is what is needed to show fresh form, .setValue is the solution here:

Component

Instead of reinitializing addForm, check if addForm was initialized previously and if so, only set value for existing FormControls:

if (this.addForm) {
    this.addForm.setValue({
        selectedCountry: null
    })
} else {

    let formTemp: any = {
        selectedCompany: new FormControl(null, [Validators.required]),
    }

    this.addForm = this._formBuilder.group(formTemp);
}

In this way, I figured, reference is not lost to old addForm, so no error occurs.

17
votes

My solution for that is to replace formControlName with formControl.

Instead of

<my-custom-component formControlName="selectedCompany"></my-custom-component>

use

<my-custom-component [formControl]="addForm.controls['selectedCompany']"></my-custom-component>

or with some getMethod for taking formControl

Works also with error:

There is no FormControl instance attached to form control element with path

where I've used some FormArray.

2
votes

I found a wierd "solution" to this. So to reset the subcomponents, which use the formGroup and get confused when you swap it out. I use this hack.

comp.ts

public flicker: boolean = false;

reInit() {
    this.flicker = true;

    this.addForm = this._formBuilder.group({
         selectedCompany: new FormControl(null, [Validators.required]),
    });

    setTimeout( () => this.flicker = false, 200); //On very heavy pages, timeout ensures that the flicker hack works as expected.
}

comp.html

<form [formGroup]="addForm" *ngIf="!flicker">
     ...
     <my-custom-component formControlName="selectedCompany"></my-custom-component>
     ...
</form>

Horrendeous hack, which basically enforces the formGroup components to destroy and re-initialize themselves, but desperate times call for desperate measures...

I needed this hack, because I use FormGroup objects to save the results of a form into an interim array of results, each of which can be re-opened and edited at will. In the future, I will be making ngModel based form state saving, to avoid this issue, but a temporary solution is here.

Edit 1

setTimeout( () => this.flicker = false, 200); //On very heavy pages, timeout ensures that the flicker hack works as expected.

There is a better way to synchronously do the flicker

this.flicker = true;
this._changeDetectorRef.detectChanges();
this.flicker = false;
this._changeDetectorRef.detectChanges();

detect changes will synchronously run the change detection and update the view, thus removing the old formgroup.