表单控件 valueChanges 给出之前的值

Form control valueChanges gives the previous value

我在表单对象 parentForm 中有一个名为 'question1' 的表单控件,我已经通过以下方式订阅了它。

它是一个单选按钮,有两个选项 YesNo,当我 select No 我得到 Yes 当我 select YesNo.

this.parentForm.controls['question1'].valueChanges.subscribe(
  (selectedValue) => {
    // If option `No is selected`
    console.log(selectedValue);  // displays No. OK
    console.log(this.parentForm.value['question1']);  // displays Yes. Problem is here
  }
);

selectedValue 变量具有正确的值,但如果我这样做 console.log(this.parentForm.value['question1'] 它会给出以前的值。

我试图在从 this.parentForm.value['question1'] 检索值之前放置一个 setTimeout(),它工作正常。

setTimeout(() => {
  console.log(this.parentForm.value['question1']); // gives the correct value.
}, 500);

但我的问题是为什么 parentForm 在其控件的值更改时没有更新,而且我也是在值更改后才检索它的值。

注意:我不想观察 parentForm.valueChanges,这不是我的要求。

valueChanges事件被触发新值更新为FormControl值之后,在[=22=之前] ] 更改冒泡到其父级和祖先级。因此,您将必须访问 FormControl 本身的值(刚刚被修补),而不是 FormGroup 值对象的字段(在事件期间未被触及)。

鉴于此,请改用 this.parentForm.get('question1').value

this.parentForm.controls['question1'].valueChanges.subscribe(
    (selectedValue) => {
      console.log(selectedValue);
      console.log(this.parentForm.get('question1').value);     
    }
);

还有一种选择,但它可能并不适合所有情况:您可以等待 one tick 在 FormControl 中更新 selectedValue 之前:

setTimeout( () => console.log( selectedValue ) );

有关 sync/async 表单主题的更多信息:Reactive forms 在 Angular 指南文档中。

尝试这样做

this.parentForm.controls['question1'].valueChanges.subscribe(
    (selectedValue) => {
      console.log(selectedValue);
      console.log(this.parentForm.value.question1);     
    }
);

如果更新了 FormBuilder 的控件,您可以立即通过 属性 值

从 FormBuilder 对象恢复最后的值

valueChanges 是一个 Observable,因此您可以通过管道 pairwise 获取订阅中的上一个和下一个值。

// No initial value. Will emit only after second character entered
this.form.get('fieldName')
  .valueChanges
  .pipe(pairwise())
  .subscribe(([prev, next]: [any, any]) => ... );
// Fill buffer with initial value, and it will emit immediately on value change
this.form.get('fieldName')
  .valueChanges
  .pipe(startWith(null), pairwise())
  .subscribe(([prev, next]: [any, any]) => ... );

它在 StackBlitz 中的工作示例: https://stackblitz.com/edit/angular-reactive-forms-vhtxua

更新

如果您注意到 startWith 似乎已弃用,但事实并非如此。操作员只有一个活动签名,您可以在 .

中阅读相关信息

Highly likely, you are using startWith(null) or startWith(undefined), they are not deprecated despite the notice, but IDE detects a wrong function signature, which is deprecated, and shows the warning.

一个简单的解决方法是提供预期的 return 类型:

// Prevent deprecation notice when using `startWith` since it has not been deprecated
this.form.get('fieldName')
  .valueChanges
  .pipe(startWith(null as string), pairwise())
  .subscribe(([prev, next]: [any, any]) => ... );

它在 StackBlitz 中与 startWith 一起工作的示例: https://stackblitz.com/edit/angular-reactive-forms-rvxiua