修补表单时,控件的更改检测如何工作?

How does change detection on control work when form is patched?

我想知道以下情况会发生什么:

我有一个带有这些控件的 formGroup:

{
  forename: new FormControl()
  surname: new FormControl()
}

现在我跟踪控件的变化 'surname' 像这样(只是一个例子):

this.formGroup.get('surname').valueChanges.subscribe(changes => {
   if(this.formGroup.get('forename') == 'Max'){
      this.formGroup.get('forename').disable();
   }
})

最后我像这样修补我的表单:

this.formGroup.patchForm({surname: 'Muster', forename: 'Max'});

控件'forename'会被禁用吗?因为我不确定它是否会在设置控件'forename'的值之前触发控件'surname'的更改。因此 'forename' 可能还没有 'correct' 值。

我试图更好地理解,当触发 exactle valueChanges 事件时,因为我有时会遇到问题,即值未设置,尽管它们应该设置。

我也想知道是否可以等到每个控件都被修补后再发出更改。

原因:

valueChanges for surname 将在 patchValue() 更新第一个 属性 后立即触发,因此您将获得 null 作为 forename 条件 this.formGroup.get('forename') == 'Max' 将是 false.

解决方案一:

你可以subscribe()valueChanges整个formGroup而不是单独控制然后检查需要的条件。像这样:

this.formGroup
      .valueChanges // subscribe to all changes
      .pipe(
        filter(form => form.forename === 'Max') // check if 'forname' is 'Max'
      ).subscribe(
        forename => this.formGroup.get('forename').disable() // disable control
      );

方案二:

只需更改要更新的对象中的道具顺序,您就可以通过代码获得所需的行为。像这样:

this.formGroup.patchForm({ forename: 'Max', surname: 'Muster' });

Working Demo with Solution 1

这就是我最后做的事情:

this.formGroup.get('surname').valueChanges.subscribe(changes => {
   this.handleForenameControl();
})

this.formGroup.get('forename').valueChanges.subscribe(changes => {
   this.handleForenameControl();
})

private handleForenameControl():void{
  if(this.formGroup.get('forename') == 'Max'){
      this.formGroup.get('forename').disable();
   }
}

我知道这不是最干净的,我正在考虑不放另一个 valueChanges-Subscription,但是是的。

我的意思是上面只是一个例子,没有我在项目中实际使用的代码,所以这个例子可能不好。也许这仍然对某人有帮助。