当表单拆分为子组件时,无法根据选择字段重置输入值

时间:2017-04-25 22:25:40

标签: angular angular-reactive-forms

我正在显示并隐藏基于同一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的帮助下,我创建了一个显示错误的plunker。只需在选择字段中将other更改为another,然后观察控制台即可注销错误。该错误似乎与将FormGroup拆分为子组件以减少每个类中的大小和逻辑有关。

如果查看创建的第一个plunker,则表单封装在app-component中时不会发生错误。

1 个答案:

答案 0 :(得分:3)

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

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

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

NgControlStatus指令检查验证状态。

在第一次检查时,您的表格有效

enter image description here

之后,您正在调用formGroup.get('other_source_desc').reset();并且状态为invalid

enter image description here

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

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

没有可见的副作用

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

  

这条规则对于Angular的单向数据流非常重要。&#34;政策。   您永远不应该担心读取组件值可能会发生变化   其他一些显示值。整个视图应该是稳定的   单一渲染过程。

为了解决您的问题,我做了以下事情:

1)向ngModelChange控件

添加了select个事件
<select formControlName="source" (ngModelChange)="sourceChanged($event, i)">

2)将副作用从hasOtherFundingSource移到sourceChanged函数

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

<强> Modified Plunker