在加载我的 parent 组件时,我正在使用patchValue更新该(父)组件的形式 .
在我的孩子ControlValueAccessor组件的表单组件上也有一个表单组 . 因此,在我的writeValue函数中,我正在更新子组件有关从父组件patchValue传递的值 .
我的writeValue函数看起来像这样:
writeValue(value: CountryAndCity): void {
if (value != null && value.country && value.city) {
this.isDefaultValueDefined = true;
this.form.patchValue({country: value.country});
this.form.patchValue({city: value.city});
**this.cdRef.detectChanges();**
}
}
正如你所看到的,我不得不使用detectChanges()作为上述函数的最后一行,因为没有它我得到错误:
ParentComponent.html:1 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ng-pristine: true'. Current value: 'ng-pristine: false'.
我想我明白为什么会这样 . Angular开始检查父组件,然后,开始检查子组件,然后,在子组件上,子组件,在writeValue函数上更改父组件的表单状态 .
我对使用detectChanges()感到不舒服 . 有没有办法做别的事情?是否必须使用父组件和子组件,每个组件都有formGroup,子组件是父formgroup formControl之一?
2 回答
我不认为,这是因为你的
write
函数而发生的,而是你的表单中的某些内容在创建子项后立即发出值,但是如果没有看到更多的代码就很难分辨 .我遇到了同样的问题,所以我在没有手动触发变化检测的情况下防止此错误的做法是将值传播与当前更改检测周期中的父传播分离 .
实现这一目标的一个简单方法是在上游的值中使用
yield
我不知道这是否是最好的方法,但对我来说它是有效的 .
顺便说一句:我还建议使用
{emitEvent: false}
作为补丁选项,这可以防止孩子在write
函数中触发事件 . 如果您对错误来源的假设是正确的,那么这将解决您的问题,但如果我的假设是真的则不会 .角度应用程序状态更改可能来自:
活动
XHR
计时器
但是当您使用控制值访问器编写值时,需要使用
ChangeDetectorRef
和detectChanges()
告知角度更新更改你应该看一下Pascal Precht的文章Who notifies Angular