Angular Material Form中的自定义验证

时间:2018-03-02 12:40:49

标签: angular angular-material angular5 angular-material2

我正在实施更改密码屏幕我需要检查密码和确认密码的相等性。所以我正在实施自定义验证。

但我得到一些例外" matcher.isErrorState不是一个函数"。请在下面找到我的代码,让我知道我身边缺少的东西。

TypeScript文件 -

export class ChangePasswordComponent  implements OnInit {
  password :any;
  confirmPassword:any;
  form  :any ;
  constructor(fb: FormBuilder, private authService: AuthService, private router: Router) {

    this.password = new FormControl('', [Validators.required,Validators.minLength(8) , Validators.maxLength(20), Validators.pattern(new RegExp("(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])"))]);
    this.confirmPassword = new FormControl('', [Validators.required, Validators.minLength(8) , Validators.maxLength(20)]);

    this.form = fb.group({
      password  :this.password ,
      confirmPassword :this.confirmPassword
          });
    var that = this;
    this.form.controls.confirmPassword.setValidators([this.cross(this.password)]);

  }

  cross(  p) {
    console.log("in cross");
    console.log(p);
    return null;
 }
    }

Html组件文件 -

<form  [formGroup]="form" class="example-form"  >

    <mat-form-field style="width: 100%">
        <input matInput placeholder="Enter your password" [type]="'password'" formControlName="password" required>
        <mat-error *ngIf="form.controls.password.invalid">{{validatePassword()}}</mat-error>
    </mat-form-field>
    <br>
    <br>
    <mat-form-field style="width: 100%">
        <input matInput placeholder="Confirm your password" [type]="'password'"    formControlName="confirmPassword" required>
        <mat-error *ngIf="form.controls.confirmPassword.invalid">{{validateConfirmPassword()}}</mat-error>
    </mat-form-field>

    <br>
    <button color="primary" (click)="changePassword()" [disabled]="!(form.controls.confirmPassword.valid || form.controls.password.valid)" mat-raised-button>Submit</button>

</form>

3 个答案:

答案 0 :(得分:1)

查看这篇文章,我认为将为您提供一个很好的理解{i 3}}

基本上你需要做的是分配给de confirm密码控制这样的自定义验证器:

FAIL["test_should_update_preference", Minitest::Result, 1.8134876039985102]
 test_should_update_preference#Minitest::Result (1.82s)
        Expected response to be a redirect to <http://www.example.com/preferences> but was a redirect to <http://www.example.com/institutes>.
        Expected "http://www.example.com/preferences" to be === "http://www.example.com/institutes".
        test/controllers/preferences_controller_test.rb:20:in `block in <class:PreferencesControllerTest>'

然后你可以通过传递密码formControl

来使用这个验证器
export const confirmValidator = (password: FormControl) => 
  (confirmPassword: FormControl): ValidationErrors | null => {

    // return a object with error type if there is some kind of error 
    // return  null if there is no error

 }

试试这个让我知道

答案 1 :(得分:0)

创建自定义指令equal-validator.directive.ts

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(() => EqualValidatorDirective), multi: true }
    ]
})
export class EqualValidatorDirective {

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

Html(在确认密码字段中使用validateEqual =“password”)

<form class="login-form" (ngSubmit)="onSubmit(f)" #f="ngForm">
                <div class="col-lg-12 header">
                    Member Register
                </div>
                <div class="form-group">
                    <div class="col-lg-12">
                        <mat-form-field class="example-full-width">
                            <input type="password" matInput placeholder="Password" name="password" [(ngModel)]="user.password" #password="ngModel" required
                                minlength="8" maxlength="20" pattern="((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{8,20})">

                        </mat-form-field>
                    </div>
                    <div class="col-lg-12">

                        <mat-error *ngIf="password.touched">
                            <mat-error *ngIf="password.errors?.required">

                                Password is
                                <strong>required</strong>
                            </mat-error>
                            <mat-error *ngIf="password.errors?.pattern">

                                Password is
                                <strong>Invalid</strong>
                            </mat-error>
                        </mat-error>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-lg-12">
                        <mat-form-field class="example-full-width">
                            <input type="password" matInput placeholder="Confirm Password" name="confirmPassword" [(ngModel)]="user.confirmPassword"
                                #confirmPassword="ngModel" required validateEqual="password">

                        </mat-form-field>
                    </div>
                    <div class="col-lg-12">

                        <mat-error *ngIf="confirmPassword.touched">
                            <mat-error *ngIf="confirmPassword.errors?.required">

                                Confirm Password is
                                <strong>required</strong>
                            </mat-error>

                            <mat-error *ngIf="!(confirmPassword.valid || confirmPassword.pristine)">

                                Password amd Confirm Password is
                                <strong>Not matched</strong>
                            </mat-error>

                        </mat-error>
                    </div>
                </div>




                <div class="form-group">
                    <div class="col-lg-12">
                        <button mat-button [disabled]="f.invalid">Register</button>
                    </div>

                    <div class="col-lg-12">
                        <div class="center">
                            <mat-error>
                                {{messageText}}
                            </mat-error>
                        </div>
                    </div>
                </div>

</form>

答案 2 :(得分:0)

实际上,您正在验证表单中的两个字段如何相互交互(“密码”和“确认密码”字段)。这称为“ 跨领域验证

这意味着您的自定义验证器不能仅分配给1个字段。需要将自定义验证器分配给公共父窗体,即表单。

这是官方记录的最佳实践,用于验证表单中的2个字段如何相互影响

https://angular.io/guide/form-validation#cross-field-validation

此代码段对我有用

模板:

<form method="post" [formGroup]="newPasswordForm">
  <input type="password" formControlName="newPassword" />
  <input type="password" formControlName="newPasswordConfirm" />
  <div class="err-msg" *ngIf="newPasswordForm.errors?.passwordMismatch && (newPasswordForm.touched || newPasswordForm.dirty)">
        confirm-password does not match password
      </div>
</form>

component.ts:

export class Component implements OnInit {
    this.newPasswordForm = new FormGroup({
      'newPassword': new FormControl('', [
        Validators.required,
      ]),
      'newPasswordConfirm': new FormControl('', [
        Validators.required
      ])
    }, { validators: passwordMatchValidator });
}

export const passwordMatchValidator: ValidatorFn = (formGroup: FormGroup): ValidationErrors | null => {
  return formGroup.get('newPassword').value === formGroup.get('newPasswordConfirm').value ?
    null : { 'passwordMismatch': true };
}

请注意,对于passwordMatchValidator,它在组件类之外。它不在课程之内