当表单拆分为子组件时无法基于 Select 字段重置输入值
Can't Reset Input Value Based on Select Field When Form Split into Child Components
我正在显示和隐藏一个基于同一 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。只需在 select 字段中将 other
更改为 another
并观察控制台注销错误。该错误似乎与将 FormGroup 拆分为子组件以减少每个 class.
中的大小和逻辑有关
如果您查看创建的第一个 plunker,当表单封装在应用程序组件中时不会发生错误。
您应该避免在每次视图检查时执行的函数中产生任何副作用
<div *ngIf="hasOtherFundingSource(i)">
hasOtherFundingSource
函数将在每个应用程序 tick 的开发模式下执行两次。
有 NgControlStatus
检查验证状态的指令。
第一次检查您的表格是否有效
之后您调用 formGroup.get('other_source_desc').reset();
并且状态变为 invalid
那么 angular 就是 运行 view.checkNoChanges()
你得到 ExpressionChangedAfterItHasBeenCheckedError
所以根据https://angular.io/docs/ts/latest/guide/template-syntax.html#!#no-visible-side-effects
没有可见的副作用
模板表达式不应更改目标值以外的任何应用程序状态 属性。
This rule is essential to Angular's "unidirectional data flow" policy.
You should never worry that reading a component value might change
some other displayed value. The view should be stable throughout a
single rendering pass.
为了解决您的问题,我执行了以下操作:
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();
}
}
我正在显示和隐藏一个基于同一 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。只需在 select 字段中将 other
更改为 another
并观察控制台注销错误。该错误似乎与将 FormGroup 拆分为子组件以减少每个 class.
如果您查看创建的第一个 plunker,当表单封装在应用程序组件中时不会发生错误。
您应该避免在每次视图检查时执行的函数中产生任何副作用
<div *ngIf="hasOtherFundingSource(i)">
hasOtherFundingSource
函数将在每个应用程序 tick 的开发模式下执行两次。
有 NgControlStatus
检查验证状态的指令。
第一次检查您的表格是否有效
之后您调用 formGroup.get('other_source_desc').reset();
并且状态变为 invalid
那么 angular 就是 运行 view.checkNoChanges()
你得到 ExpressionChangedAfterItHasBeenCheckedError
所以根据https://angular.io/docs/ts/latest/guide/template-syntax.html#!#no-visible-side-effects
没有可见的副作用
模板表达式不应更改目标值以外的任何应用程序状态 属性。
This rule is essential to Angular's "unidirectional data flow" policy. You should never worry that reading a component value might change some other displayed value. The view should be stable throughout a single rendering pass.
为了解决您的问题,我执行了以下操作:
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();
}
}