Angular - 响应式表单处于挂起状态

Angular - Reactive forms has pending state

我在一个 Angular 项目中,我使用的是反应形式。我想做的是添加我自己的验证器。为此,我需要检查该 ID 是否存在于数据库中。出于这个原因,我使用了一个异步验证器。如果 id 已经被另一个元素使用,那么它必须 return 一个错误。否则,表格将有效。

这是验证器。

    export class ValidadorOperationId {
      static createValidatorOperationId(name, operationListService: OperationsListService, time: number = 500): AsyncValidatorFn {
        return (control: AbstractControl): Observable<ValidationErrors> => {
          return timer(time).pipe(
            switchMap(() => operationListService.getOperationsByUuid(name, control.value)),
            map(res => {
              return res ? { operationIdExist: true } : null
              }
            )
          );
        };
      }
    }

这就是我在组件中调用验证器的方式。

 this.fb.group({
   value: [this.operationDetails['operationid'], [Validators.required], ValidadorOperationId.createValidatorOperationId(this.nombre,this.operationListService)]
 })

问题是控件有status: pending,不知道是什么问题

如果您需要更多代码,请问我。

谁能帮帮我?

2020 年 10 月 22 日更新

我检查过 status:pending 仅在服务没有 return 任何内容(错误 404)时出现

确保你的 getOperationsByUuid return 至少是一个可观察的或一个承诺,即使你收到 404 错误。这可能是它卡在挂起状态的原因,因为这个函数没有 return 任何东西,所以你的 observable 不会发出。
注意水龙头运算符。如果此日志未打印,这就是它保持待处理状态的原因,因为它永远不会解析。

    export class ValidadorOperationId {
      static createValidatorOperationId(name, operationListService: OperationsListService, time: number = 500): AsyncValidatorFn {
        return (control: AbstractControl): Observable<ValidationErrors> => {
          return timer(time).pipe(
            switchMap(() => operationListService.getOperationsByUuid(name, control.value)),
            tap(res => console.log('this should print')),
            map(res => {
              return res ? { operationIdExist: true } : null
              }
            ),
            take(1) // not useful if getOperationsByUuid is an http call (http calls always complete)
          );
        };
      }
    }

要处理 404 或任何其他 http 错误,您可以使用 RxJS 的 catchError 运算符。下面是你的验证器的样子 -

export class ValidadorOperationId {
      static createValidatorOperationId(name, operationListService: OperationsListService, time: number = 500): AsyncValidatorFn {
        return (control: AbstractControl): Observable<ValidationErrors> => {
          return timer(time).pipe(
            switchMap(() => operationListService.getOperationsByUuid(name, control.value)
           .pipe(catchError(err => of(null))), // <-- this is what you need
            map(res => {
              return res ? { operationIdExist: true } : null
              }
            )
          );
        };
      }
    }