Величина контроля формыChanges дает предыдущее значение

У меня есть форма управления с именем 'question1' внутри объекта формы parentForm, и я подписался на него следующим образом.

Его переключатель с двумя параметрами Yes и No, когда я выбираю No, я получаю Yes и когда я выбираю Yes его 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 переменная имеет правильное значение, но если я делаю console.log(this.parentForm.value['question1'], она дает предыдущее значение.

Я попытался поставить setTimeout() до получения значения из this.parentForm.value['question1'], он просто отлично работает.

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

Но мой вопрос в том, почему parentForm не обновляется, когда изменяется его управляющее значение, и что я тоже возвращаю его значение только после того, как значение было изменено.

Примечание. Я не хочу наблюдать за parentForm.valueChanges, а не по моему требованию.

Ответ 1

Событие valueChanges запускается после, новое значение обновляется до значения FormControl, а до изменение перерисовывается до его родителя и предков. Поэтому вам нужно будет получить доступ к самому самому FormControl (который только что был исправлен), а не к полю объекта значения FormGroup (который нетронутым во время события).

В свете этого используйте this.parentForm.get('question1').value вместо этого:

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

Ответ 2

Есть еще один вариант, но во всех случаях он не подходит: вы можете подождать один галочку перед обновлением selectedValue в FormControl:

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

Подробнее о теме формы sync/async:

Ответ 3

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

Ответ 4

Попробуйте сделать это

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

Если элементы управления FormBuilder были обновлены, вы можете немедленно восстановить последние значения из объекта FormBuilder через значение свойства