我正在尝试将应用程序迁移为使用
ChangeDetectionStrategy.OnPush
。然而,我在尝试使用一些反应形式时遇到了一些阻碍。
我有一个可重用的控件,可以根据某些状态标志(例如
*ngIf="control.touched && control.invalid"
)显示验证消息。我遇到的问题是,无法检测 touched
标志何时更改,因此无法使用 ChangeDetectorRef
触发更改检测。
可以通过监听 click
事件来引用输入元素本身来完成,但这并不能说明何时使用
markAsTouched()
,并且并不总是传递对元素的引用可能,但总是不优雅。有没有办法使用
OnPush
并仍然响应表单控件状态(例如
touched
),或者只是普遍痛苦?markForCheck()
来更新视图:
constructor(changeDetectorRef: ChangeDetectorRef) {
this.formGroup.statusChanges.subscribe(status => changeDetectorRef.markForCheck());
}
更新: 由于我无法发表评论,我将更新此答案。
您对 statusChanges 的看法是正确的。当然你需要订阅 statusChanges,这是一个错误。
我认为我们在这里忽略了一点。在
CheckOnce
模式(OnPush)下,Angular 将在 DOM 事件(包括模糊)之后检查更改,因此视图应该更新并且您提到的消息 (
*ngIf="control.touched && control.invalid"
) 应该起作用。但是如果您在代码中调用
markAsTouched()
,则在您调用
markForCheck()
之前不会检查更改。这是一个工作示例:https://stackblitz.com/edit/angular-6-reactive-form-validation-touched-sjhijt
//before
this.myForm=this.formBuilder({
control1:''
})
//after
this.myForm=new FormGroup({
control1:new FormControl(''),
},{ updateOn: 'blur' })
markAsTouched
的方法覆盖控件的原始
markForCheck
方法:const originalMarkAsTouched = this.control.markAsTouched;
this.control.markAsTouched = () => {
originalMarkAsTouched.call(this.control);
this.changeDetectorRef.markForCheck();
};