ExpressionChangedAfterItHasBeenCheckedError 动态反应形式

the*_*tor 3 angular

当使用嵌套反应式表单且子组件使用 ng-if* 时,会发生此异常。导致问题的是模板插值。请参阅重现:

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 {}
Run Code Online (Sandbox Code Playgroud)

yur*_*zui 5

我们一次又一次地遇到这个错误的问题......

基本上很多人都不想了解这个错误的原因是什么。因此,我们看到了很多答案,其中主要解决方案是调用第二个生命周期摘要。但在某些情况下这并没有帮助。

角度变化检测是综合机制。为了获得洞察力,您必须每天使用它并一次又一次地调试它。

首先,我强烈建议您阅读 @angularindepth-com 撰写的这篇精彩文章

现在,真相大白了……

我又创建了一个组件,例如:

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

并将其添加到根 html 而不是插值:

<form [formGroup]="myForm" novalidate>
  <my-form [parentForm]="myForm"></my-form>
</form>
<my-form-info [form]="myForm"></my-form-info> 
Run Code Online (Sandbox Code Playgroud)

现在,角度不会抱怨该错误,因为我已经更改了更改检测顺序。

NG 运行示例

也可以看看