首页 文章

Angular2中的交叉字段验证

提问于
浏览
19

我正在构建一个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 Validator,方法是传入另一个字段的名称或者接近它的东西 . 看起来这应该是一种能力,因为这在几乎任何复杂的业务应用程序UI中都是必需的 .

3 回答

  • 4

    您需要将自定义验证程序分配给完整的表单组以实现此目的 . 像这样的东西:

    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
      };
    }
    

    有关详细信息,请参阅此问题:

  • 27

    您还可以使用自定义指令验证程序来比较字段 .

    在你的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

  • 12

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

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

相关问题