有什么方法可以强制 Angular 异步验证器始终运行吗?

问题描述 投票:0回答:1

我正在将旧版 Angular 应用程序 (v7?) 一直升级到最新版本 (v17)。

我有一个包含这三个 FormControl 的 FormGroup:

username
password
confirmPassword

有两个验证器:

  1. 检查密码和确认密码字段是否匹配的同步验证器
  2. 联系服务器进行密码验证的异步验证器。这必须是服务器请求,因为我们强制执行一些取决于用户的规则,例如用户最近没有使用过相同的密码,他们的公司管理员是否设置了更严格的密码规则等。

在 Angular 文档中它指出

出于性能原因,Angular 仅在所有同步验证器都通过时才运行异步验证器。每项都必须在设置错误之前完成。

这似乎与 v7 的功能不同,因为即使存在同步错误,我的异步验证器也总是会触发。

我知道这通常是一件好事,但是因为我的密码和确认密码有一个同步验证器来检查它们是否匹配,所以用户必须输入他们想要使用的密码两次,然后才会被告知该密码无效,这这是一次奇怪的经历。

我在文档中看不到任何方法来更改特定表单、控件或验证器的此行为,因此我打算将其转换为值更改的去抖订阅,并在控件上手动设置错误,以便它将总是跑。但如果可以避免的话我宁愿不这样做 - 有谁知道这是否可以配置?

谢谢!

已经尝试过:

  • FormGroup 上的两个验证器
  • FormControl 上有一个验证器,FormGroup 上有一个验证器
  • 将两者都放在单独的 FormControls 上
  • 使匹配验证器成为“假”异步验证器(似乎仍然阻止真正的http请求触发,也许是因为它太快了?)
  • 在文档中搜索选项
  • 谷歌搜索
angular typescript
1个回答
0
投票

我不知道有什么方法可以完全满足您的要求,但我可以为您提供一个解决方案,您可以自己验证控件。

考虑一个将用户名作为输入的用户注册表单,就像您一样,我们希望使用一些服务器端验证。

我能做的就是订阅控件

valueChanges
并在异步管道中运行验证函数:

constructor() {
  const control = this.userSignUpForm.controls.firstName;
  control.valueChanges.pipe(
    takeUntilDestroyed(),
    distinctUntilChanged(),
    debounceTime(1000),
    filter((value): value is string => !!value),
    switchMap(() => AppValidators.checkValidName()(control))
  ).subscribe({
    next: validationErrors => {
      if (validationErrors) control.setErrors(validationErrors); 
    }
  })
}

我们过滤空值,然后在

switchMap
运算符内使用异步验证器。

在这个例子中,

AppValidators.checkValidName
是一个
AsyncValidatorFn
,我直接在我的RxJS流中使用它,如果你的验证器已经编写好了,它会派上用场。

之后将留下一个

ValidationErrors
对象或
null

我还使用

takeUntilDestroy
运算符,当在注入上下文(如构造函数)中使用该运算符时,将保证在组件被销毁时清除订阅。

© www.soinside.com 2019 - 2024. All rights reserved.