Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExpressionChangedAfterItHasBeenCheckedError dynamic reactive forms

Tags:

angular

This exception occurs when using nested reactive forms, when the child component uses ng-if*. It's the template interpolation that causes problems. Please see repro:

https://plnkr.co/edit/GrvjN3sJ05RSNXiSY8lo

//our root app component
import {Component, NgModule, VERSION, Input, OnInit} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
import { FormsModule,ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'my-nested-component',
  template: `
    <div [formGroup]="parentForm">

    <input formControlName="mynestedcontrol" type="text">
    </div>
  `,
})
export class MyNestedComponent implements OnInit {
  @Input() parentForm:FormGroup
  constructor(private fb: FormBuilder) {
  }

  ngOnInit() {
     this.parentForm.addControl("mynestedcontrol", new FormControl('',[]))
  }
}

@Component({
  selector: 'my-form',
  template: `<div [formGroup]="parentForm">

    <input formControlName="mycontrol" type="text">
    <a href="#" (click)="onClickShowDetails()" *ngIf="!showDetails">Show Details</a>
    <div *ngIf="showDetails">
      <my-nested-component [parentForm]="parentForm"></my-nested-component>
    </div>
    </div>
  `,
})
export class MyForm implements OnInit {
  @Input() parentForm:FormGroup
  constructor(private fb: FormBuilder) {
  }

  ngOnInit() {
     this.parentForm.addControl("mycontrol", new FormControl('',[]))
  }

  showDetails = false;

  onClickShowDetails() {
    this.showDetails = true
  }
}

@Component({
  selector: 'my-app',
  template: `<form [formGroup]="myForm" novalidate>
      <my-form [parentForm]="myForm"></my-form>
    </form>

    {{myForm.value|json}}
  `,
})
export class App {
  myForm:FormGroup
  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({})
  }

}

@NgModule({
  imports: [ BrowserModule, ReactiveFormsModule,
    FormsModule],
  declarations: [ App,MyForm,MyNestedComponent ],
  bootstrap: [ App ]
})
export class AppModule {}
like image 542
theactiveactor Avatar asked Mar 14 '26 17:03

theactiveactor


1 Answers

We run into a problem with this error again and again...

Basically many people don't want to understand what is the cause of this error. And as a result we see a lot of answers where the main solution is calling second lifecycle digest. But in some cases it won't help.

Angular change detection is comprehensive mechanism. In order to achieve insight you have to work with it every day and have to debug it again and again.

First, i strongly suggest you reading this great article by @angularindepth-com

  • https://blog.angularindepth.com/he-who-thinks-change-detection-is-depth-first-and-he-who-thinks-its-breadth-first-are-both-usually-8b6bf24a63e6

Now, the truth Is out there...

I created one more component like:

@Component({
  selector: 'my-form-info',
  template: `{{form.value|json}}`
})
export class MyFormInfoComponent {
  @Input() form: FormGroup
}

and added it to the root html instead of interpolation:

<form [formGroup]="myForm" novalidate>
  <my-form [parentForm]="myForm"></my-form>
</form>
<my-form-info [form]="myForm"></my-form-info> 

Now angular doesn't complain about that error because i've changed change detection order.

Ng-run Example

See also

  • Catch Angular template errors like a pro or how I create Angular Demo
like image 96
yurzui Avatar answered Mar 17 '26 11:03

yurzui



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!