Form control valueChanges gives the previous value

Amit Chigadani picture Amit Chigadani · Jul 4, 2017 · Viewed 80.5k times · Source

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.

Answer

mtpultz picture mtpultz · Jan 15, 2019

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