【问题标题】:Angular - Reactive forms has pending stateAngular - 反应式表单具有待处理状态
【发布时间】:2020-10-21 11:09:46
【问题描述】:

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

这是验证器。

    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,不知道怎么回事。

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

谁能帮帮我?

  • Angular 版本:8.2.14
  • Rxjs 版本:6.5.3

2020 年 10 月 22 日更新

我已检查status:pending 仅在服务未返回任何内容时出现(错误 404)

【问题讨论】:

  • 不应该将异步验证器也添加到数组中吗? value: [this.operationDetails['operationid'], [Validators.required], [ValidadorOperationId.createValidatorOperationId(this.nombre,this.operationListService)]]
  • 结果是一样的。状态继续挂起。 @MoxxiManagarm
  • 你可以创建一个显示相同行为的堆栈闪电战吗?
  • 我认为,为了工作,你的 observable 应该完成。您的getOperationsByUuid 方法是否完整?在您的地图运算符后面添加take(1),看看它是否解决了。

标签: angular asynchronous rxjs angular-reactive-forms angular-validation


【解决方案1】:

确保您的 getOperationsByUuid 至少返回一个 observable 或一个 promise,即使您收到 404 错误也是如此。这可能是它陷入挂起状态的原因,因为此函数不返回任何内容,因此您的 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 错误时,不会打印该消息。如何解决这个问题?你能帮助我吗?很抱歉给您带来不便
  • 我所做的是在 map 运算符之后添加 catchError 运算符并返回一个 observable,但我不知道这是否是最佳实践。
  • 好吧,我会在getOperationsByUUid() 中捕获并处理此错误,因为它与该调用有关。因为如果您的代码中除了 404 错误之外还有任何其他错误,它将返回一些可能导致不必要的副作用的内容。首先尝试解决为什么会出现 404 错误。
【解决方案2】:

要处理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
              }
            )
          );
        };
      }
    }

【讨论】:

    猜你喜欢
    • 2020-05-25
    • 2020-05-13
    • 2021-09-07
    • 2017-06-16
    • 2021-12-20
    • 2018-07-17
    • 2020-05-13
    • 2015-01-19
    • 1970-01-01
    相关资源
    最近更新 更多