【问题标题】:Cross field validation in Angular2Angular2中的跨字段验证
【发布时间】:2023-03-23 03:45:02
【问题描述】:

我正在构建一个 Angular2 客户端应用程序。我目前正在研究会员组件并将客户端组件与 MVC6 vNext Identity v3 集成。我编写了自定义 Angular2 密码验证器,如下所示:

needsCapitalLetter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[A-Z]/))
        return {'needsCapitalLetter': true}

    return null;
}

needsLowerLetter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[a-z]/))
        return {'needsLowerLetter': true}

    return null;            
}

needsNumber(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/\d/))
        return {'needsNumber': true}

    return null;            
}

needsSpecialCharacter(ctrl: Control): {[s: string]: boolean} {
    if(!ctrl.value.match(/[^a-zA-Z\d]/))
        return {'needsSpecialCharacter': true}

    return null;            
}

这项工作很棒,我喜欢 Angular2,但现在我正在尝试编写一个验证器来验证“确认密码”是否等于“密码”。为了做到这一点,我需要能够针对另一个字段验证一个字段。我可以轻松地在组件级别执行此操作,只需检查模糊、提交或任何其他方式,但这绕过了 Angular2 ngForm 验证系统。我非常想弄清楚如何为一个可以检查另一个字段的值的字段编写 Angular2 验证器,方法是传入另一个字段的名称或类似的名称。看起来这应该是一种能力,因为这在几乎所有复杂的业务应用程序 UI 中都是必需的。

【问题讨论】:

标签: javascript validation angular


【解决方案1】:

您需要将自定义验证器分配给完整的表单组以实现此功能。像这样的:

this.form = this.fb.group({
  name:  ['', Validators.required],
  email: ['', Validators.required]
  matchingPasswords: this.fb.group({
    password:        ['', Validators.required],
    confirmPassword: ['', Validators.required]
  }, {validator: this.matchValidator})  <--------
});

这样您就可以访问该组的所有控件,而不仅仅是一个... 这可以使用 FormGroup 的controls 属性进行访问。 FormGroup 在触发验证时提供。例如:

matchValidator(group: FormGroup) {
  var valid = false;

  for (name in group.controls) {
    var val = group.controls[name].value
    (...)
  }

  if (valid) {
    return null;
  }

  return {
    mismatch: true
  };
}

查看这个问题了解更多详情:

【讨论】:

  • 这似乎是正确的方法,直到您尝试将 form.value 发送到您的后端,并且您意识到它使用两个密码发送匹配的密码对象。除了删除匹配的密码并在发送密码之前添加密码之外,还有什么优雅的解决方案吗?
  • 如何在html中定义密码字段?我发现像 &lt;div ngFormControl="matchingPassword"&gt; 这样的东西似乎不再是最新的了。
  • 这里有一点更新。在最新的 Angular 2 中,ControlGroup 更名为FormGroup
  • 先生,我得到 'validator' 在上面使用后的 'ValidatorFn 类型中不存在?
【解决方案2】:

您还可以使用自定义指令验证器来比较字段。

在您的 html 中:

<div>
    <label>Password</label>
    <input type="password" name="password" [ngModel]="user.password" 
        required #password="ngModel">
    <small [hidden]="password.valid || (password.pristine && !f.submitted)">
        Password is required
    </small>
</div>
<div>
    <label>Retype password</label>
    <input type="password" name="confirmPassword" [ngModel]="user.confirmPassword" 
        required validateEqual="password" #confirmPassword="ngModel">
    <small [hidden]="confirmPassword.valid ||  (confirmPassword.pristine && !f.submitted)">
        Password mismatch
    </small>
</div>

还有你的指令:

import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
@Directive({
    selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true }
    ]
})
export class EqualValidator implements Validator {
    constructor( @Attribute('validateEqual') public validateEqual: string) {}

    validate(c: AbstractControl): { [key: string]: any } {
        // self value (e.g. retype password)
        let v = c.value;

        // control value (e.g. password)
        let e = c.root.get(this.validateEqual);

        // value not equal
        if (e && v !== e.value) return {
            validateEqual: false
        }
        return null;
    }
}

这是 plunkr 中的完整解决方案:

https://plnkr.co/edit/KgjSTj7VqbWMnRdYZdxM?p=preview

【讨论】:

  • 这个解决方案很好,因为它添加了一个全局相等的验证器,不像其他需要在每个模块上重新编写代码的方法。请注意,plunker 代码与此处发布的不同。
  • 很好理解。谢谢我可以在我的项目中使用这个。
【解决方案3】:

我自己没有这样做,但您可以使用两个密码字段创建 ControlGroup 并验证它。控件具有 .valueChanges 属性,这是一个可观察的,您可以将它们组合并在那里检查是否相等。

Victor Savkin 在 this episode 中简要介绍了 Angular Air 上的确切案例

【讨论】:

    猜你喜欢
    • 2020-07-06
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多