Форма застряла в состоянии PENDING с помощью асинхронного валидатора, когда значение изменилось при построении

При использовании реактивных форм с асинхронным валидатором в группе форм и при изменении значений группы форм с помощью patchValue в конструкторе или в ngOnInit - даже если наблюдаемый асинхронный валидатор завершается, форма остается в состоянии PENDING.

Я создал SSCCE в Stackblitz

В примере вы видите простую форму с двумя полями, с указанием статуса формы и состояния валидатора. В коде в ngOnInit я вызываю patchValue в форме, в результате чего форма переходит в состояние PENDING и вызывается асинхронный валидатор.

Асинхронный валидатор мало что делает, он просто ждет 1 секунду, а затем возвращает объект ошибок null, в основном говоря, что форма действительна. По указателям видно, что проверка завершена, но форма остается в состоянии PENDING.

Если вы инициируете изменение значений полей в любое время, кроме как в конструкторе или в ngOnInit (т.е. при построении объекта), тогда форма действительно переходит в состояние VALID, когда валидатор завершает работу. Это также применимо, если вы заключите изменение значения в setTimeout.

Я делаю что-то неправильно? Это нормальное поведение или ошибка в Angular?


person Aviad P.    schedule 12.11.2019    source источник
comment
Я не могу точно определить, что происходит и какие значения застряли в состоянии ожидания, но могу сказать, что это определенно связано с тем фактом, что угловые формы являются асинхронными, поэтому, когда вы вызываете patchValue слишком быстро (до того, как форма был полностью построен и установлены предыдущие значения), это вызывает это. Так что нет, это не ошибка, это вызвано асинхронностью угловых форм. Иногда возникают другие проблемы, вызванные асинхронностью форм, поэтому иногда вам нужно подождать галочку (используя settimeout), прежде чем что-то делать, вот один (не связанный) вопрос stackoverflow.com/a/58578113/6294072   -  person AJT82    schedule 13.11.2019
comment
Спасибо @ AJT82. Я бы сказал, что это либо функция (возможно, недокументированная), либо ошибка. Если это функция, ее следует описать в спецификации, если это ошибка, ее следует открыть как проблему. Но в любом случае я бы поставил предупреждение либо во время выполнения, либо во время компиляции, что patchValue не следует вызывать в том же кадре, который создает _2 _...   -  person Aviad P.    schedule 13.11.2019


Ответы (1)


У меня была аналогичная проблема, после асинхронного валидатора форма застряла на PENDING, и вот как я с этим справляюсь:
1) сделать наблюдаемым изменение статуса:

this.form$ = this.form.statusChanges;

2) подписаться на наблюдаемое:

this.form$.subscribe( r => {
  if (r === 'VALID') {
    //form valid
  } else if( r === 'PENDING') {
    setTimeout(() => {
      this.form.updateValueAndValidity(); // this function will trigger statusChange one more time.
    }, 2000);
  } else {
    // any other status
  }
});

Итак, если асинхронный валидатор завершил работу, но не запустил statusChange, все, что Вы можете сделать, это запустить statusChange еще раз самостоятельно.

person DanielWaw    schedule 26.05.2020