Cross field validation in Angular2

后端 未结 3 445
情话喂你
情话喂你 2020-12-02 16:29

I\'m building an Angular2 client side application. I\'m currently working on the membership components and integrating client side components with MVC6 vNext Identity v3.

相关标签:
3条回答
  • 2020-12-02 16:32

    You can also use a custom directive validator to compare the fields.

    In your 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>
    

    And your directive:

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

    Here is the complete solution in plunkr:

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

    0 讨论(0)
  • 2020-12-02 16:42

    You need to assign a custom validator to a complete form group to implement this. Something like this:

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

    This way you will have access to all controls of the group and not only one... This can be accessed using the controls property of the FormGroup. The FormGroup is provided when validation is triggered. For example:

    matchValidator(group: FormGroup) {
      var valid = false;
    
      for (name in group.controls) {
        var val = group.controls[name].value
        (...)
      }
    
      if (valid) {
        return null;
      }
    
      return {
        mismatch: true
      };
    }
    

    See this question for more details:

    • Angular2 validator which relies on multiple form fields
    0 讨论(0)
  • 2020-12-02 16:44

    I haven't done this myself, but you could create ControlGroup with two password fields and validate it. Controls have .valueChanges property which is an observable and you can combine them and check for equality there.

    Victor Savkin talks briefly about that exact case on Angular Air in this episode

    0 讨论(0)
提交回复
热议问题