Form control valueChanges gives the previous value

青春壹個敷衍的年華 提交于 2019-12-04 08:15:20

问题


I have a form control with name 'question1' within the form object parentForm and I have subscribed to it in the following way.

Its a radio button with two options Yes and No, when I select No I get Yes and when I select Yes its a No.

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 variable has the correct value but if I do console.log(this.parentForm.value['question1'] it gives the previous value.

I tried to put a setTimeout() before retrieving value from this.parentForm.value['question1'], It just works fine.

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

But my question is why parentForm is not updated when its control's value changes and that too I am retrieving its value only after value was changed.

Note: I don't want to observe for parentForm.valueChanges, not my requirement.


回答1:


valueChanges is an Observable so you can pipe pairwise to get the previous and next values in the subscription.

// 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]) => ... );

Example of it working in StackBlitz: https://stackblitz.com/edit/angular-reactive-forms-vhtxua




回答2:


The valueChanges event is fired after the new value is updated to the FormControl value, and before the change is bubbled up to its parent and ancestors. Therefore, you will have to access the value of the FormControl itself (which has just been patched), not a field of the FormGroup value object (which is untouched during the event).

In light of that, use this.parentForm.get('question1').value instead:

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



回答3:


There is one more option, but it might not be suitable in all cases: you can wait one tick before the selectedValue is updated in FormControl:

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

More on sync/async forms topic: Reactive forms in Angular Guide docs.




回答4:


Try to do this

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

if controls of FormBuilder was updated, you can immediately recover last values from FormBuilder object through the property value



来源:https://stackoverflow.com/questions/44898010/form-control-valuechanges-gives-the-previous-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!