3

我正在显示和隐藏基于同一 FormGroup 中另一个 FormControl 的 FormControl,它使用下面的方法工作,但是当我尝试重置隐藏的输入以便提交时,它的值未发送,我收到以下错误。

组件方法

public hasOtherFundingSource(index: number) {
  const formGroup = this.overviewFunds.at(index);
  const source = formGroup.get('source').value;

  if (source !== 'other') {
    formGroup.get('other_source_desc').reset(); // Throws error
    return false;
  } else {
    return true;
  }
}

错误

ExampleComponent.html:12 ERROR Error: 
ExpressionChangedAfterItHasBeenCheckedError: 
Expression has changed after it was checked. 
Previous value: 'true'. Current value: 'false'.

在@yurzui的一些帮助下,我创建了一个显示错误的插件。只需在选择字段中更改otheranother并观察控制台注销错误。该错误似乎与将 FormGroup 拆分为子组件以减少每个类中的大小和逻辑有关。

如果您查看创建的第一个plunker,则当表单封装在应用程序组件中时不会发生错误。

4

1 回答 1

3

您应该避免在每次视图检查时执行的函数中的任何副作用

<div *ngIf="hasOtherFundingSource(i)">

hasOtherFundingSource函数将在每个应用程序滴答时在开发模式下执行两次。

NgControlStatus检查验证状态的指令。

第一次检查您的表格是否有效

在此处输入图像描述

之后你打电话formGroup.get('other_source_desc').reset();和状态变成了invalid

在此处输入图像描述

然后角度正在运行view.checkNoChanges(),你得到ExpressionChangedAfterItHasBeenCheckedError

所以根据https://angular.io/docs/ts/latest/guide/template-syntax.html#!#no-visible-side-effects

没有明显的副作用

模板表达式不应更改目标属性值以外的任何应用程序状态。

这条规则对于 Angular 的“单向数据流”策略是必不可少的。您永远不必担心读取组件值可能会更改某些其他显示值。视图应该在单个渲染过程中保持稳定。

为了解决您的问题,我执行了以下操作:

1) 增加ngModelChange事件select控制

<select formControlName="source" (ngModelChange)="sourceChanged($event, i)">

2) 将副作用从hasOtherFundingSourcesourceChanged 函数移到

sourceChanged(value: string, index: number) {
  if (value !== 'other') {
      const formGroup = this.overviewFunds.at(index);
      formGroup.get('other_source_desc').reset();
  }
}

修改后的 Plunker

于 2017-04-27T04:08:14.527 回答