密码和确认密码字段验证angular2反应形式

时间:2017-04-19 05:49:17

标签: angular angular2-forms

我需要使用反应式表格angular2检查密码和确认密码字段是否具有相同的值。我确实在这里看到了很多答案,Angular 2 form validating for repeat passwordComparing fields in validator with angular2,但似乎没有一个对我有用。可以请某人帮忙。“这个”在我的验证函数中未定义:(。 分享我的代码,

this.addEditUserForm = this.builder.group({
            firstName: ['', Validators.required],
            lastName: ['', Validators.required],
            title: ['', Validators.required],
            email: ['', Validators.required],
            password: ['', Validators.required],
            confirmPass: ['', [Validators.required, this.validatePasswordConfirmation]]
        });
validatePasswordConfirmation(group: FormGroup): any{
        let valid = true;
        // if (this.addEditUserForm.controls.password != this.addEditUserForm.controls.confirmPass) {
        //     valid = false;
        //     this.addEditUserForm.controls.confirmPass.setErrors({validatePasswordConfirmation: true});
        // }
        return valid;
    }

9 个答案:

答案 0 :(得分:31)

这最终对我有用 -

raw_sql

答案 1 :(得分:22)

最好是在表单组中有一个嵌套组,我们有一个自定义验证器,用passwordconfirmPass检查表单组,因此当更改任一字段时,验证程序被解雇,因为之前它仅在confirmPass字段被修改时触发。

所以在外部表单组中执行类似的操作:

// ...
passwords: this.fb.group({
  password: ['', [...]],
  confirmPass: ['', [...]]
}, {validator: this.checkPasswords}) // add a validator for the whole group
// ...

然后验证器看起来像这样:

checkPasswords(group: FormGroup) { // here we have the 'passwords' group
  let pass = group.get('password').value;
  let confirmPass = group.get('confirmPass').value;

  return pass === confirmPass ? null : { notSame: true }     
}

然后可以像这样显示验证错误:

*ngIf="addEditUserForm.hasError('notSame', 'passwords')"

当然,您不需要拥有嵌套组,但每次表单发生任何更改时都不会触发自定义验证程序。这样,只有在此内部表单组发生更改时才会触发。

答案 2 :(得分:3)

我在实现它时遇到了一些问题,当我使用自定义验证器和 errorStateMatcher 实现它时,我遇到了 formbuilder.group 函数已被弃用的问题,但经过一些检查后,我发现我的验证器必须更改以符合要求到群功能。

控制器看起来像这样:

// ...
addEditUserForm: FormGroup;
passwordMatcher = new ComparisonErrorStateMatcher();

constructor(private formBuilder: FormBuilder) {
  this.addEditUserForm = this.formBuilder.group({
    password: ['', Validators.required],
    confirmPass: ['', Validators.required],
  }, { validators: [MatchValidator.validate] }); // add validator to group
}
// ...

我的验证器看起来像这样:

export class MatchValidator {
  // (group: AbstractControl) is the form group but needs to be AbstractControl instead of (group: FormGroup) to remove deprecation warning. 
  static validate(group: AbstractControl): ValidationErrors | null { 
    const password = group.get('password')?.value;
    const confirmPassword = group.get('confirmPass')?.value;

    return password === confirmPass ? null : { notMatching: true }
  };
}

我的 ErrorStateMatcher 看起来像这样:

export class ComparisonErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent?.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent) && (control?.touched ?? false);
  }
}

最后,HTML 必须看起来像这样:

<form [formGroup]="addEditUserForm">

  <mat-form-field >
    <mat-label>password</mat-label>
    <input formControlName="password"
           matInput />
    <mat-error *ngIf="newPasswordForm.hasError('required')">
      password is required
    </mat-error>
  </mat-form-field>

  <mat-form-field>
    <mat-label>confirm password</mat-label>
    <input formControlName="confirmPass"
           [errorStateMatcher]="passwordMatcher"
           matInput />
    <mat-error *ngIf="newPasswordForm.hasError('notMatching')">
      passwords don't match
    </mat-error>
  </mat-form-field>
</form>

这将创建一个包含两个需要匹配的输入字段的表单。

答案 3 :(得分:1)

如果你想这样做,你需要将函数绑定到当前的“this”上下文。 传递this.validatePasswordConfirmation.bind(this)但请注意,此函数将通过FormControl进行确认,而不是像您在函数签名中所述的FormGroup。

答案 4 :(得分:1)

我采用了一种适用于任何控制的不同方法。首先,我定义了表单的基本控件:

    this.myForm = this.formBuilder.group({
            name: ['', Validators.required],
            password: ['', Validators.required],
    });

然后我创建一个新控件以使用我的自定义验证器确认该值:

    const confirmPasswordControl = new FormControl('', {
            validator: sameValueAs(this.myForm, 'password')
    });

    this.myForm.addControl('confirmPassword', confirmPasswordControl);

sameValueAs验证器的代码如下,您可以在separte文件中定义它以便在任何地方使用

export function sameValueAs(group: FormGroup, controlName: string): ValidatorFn {
    return (control: FormControl) => {
          const myValue = control.value;
          const compareValue = group.controls[controlName].value;

          return (myValue === compareValue) ? null : {valueDifferentFrom:controlName};

    };
}

答案 5 :(得分:1)

您的答案应该可以正常工作。您需要做的就是添加 .value

喜欢这里:

this.addEditUserForm = this.builder.group({
            firstName: ['', Validators.required],
            lastName: ['', Validators.required],
            title: ['', Validators.required],
            email: ['', Validators.required],
            password: ['', Validators.required],
            confirmPass: ['', [Validators.required, this.validatePasswordConfirmation]]
        });
validatePasswordConfirmation(group: FormGroup): any{
        let valid = true;
         if (this.addEditUserForm.controls.password**.value** != this.addEditUserForm.controls.confirmPass**.value**) {
             valid = false;
           this.addEditUserForm.controls.confirmPass.setErrors({validatePasswordConfirmation: true});
        // }
        return valid;
    }

答案 6 :(得分:1)

使用响应式表单 - 我认为这是最简单的方法

更改密码.ts

passwordChangeForm = new FormGroup(
    {
      currentPassword: new FormControl("", [
        Validators.required,
        Validators.minLength(6),
      ]),
      newPassword: new FormControl("", [
        Validators.required,
        Validators.minLength(6),
      ]),
      confirmNewPassword: new FormControl("", [
        Validators.required,
        Validators.minLength(6),
      ]),
    },
    {
      validators: (control) => {
        if (control.value.newPassword !== control.value.confirmNewPassword) {
          control.get("confirmNewPassword").setErrors({ notSame: true });
        }
        return null;
      },
    }
  );

更改密码.html

<div>
  <h1 mat-dialog-title>Change Password</h1>
  <form [formGroup]="passwordChangeForm">
    <mat-form-field appearance="outline">
      <mat-label>Current Password</mat-label>
      <input matInput formControlName="currentPassword" type="password" />
    </mat-form-field>
    <mat-form-field appearance="outline">
      <mat-label>New Password</mat-label>
      <input matInput formControlName="newPassword" type="password" />
    </mat-form-field>
    <mat-form-field appearance="outline">
      <mat-label>Confirm New Password</mat-label>
      <input matInput formControlName="confirmNewPassword" type="password" />
      <mat-error
        *ngIf="passwordChangeForm.get('confirmNewPassword').hasError('notSame')"
      >
        New Password Doesn't match
      </mat-error>
    </mat-form-field>
  </form>
  <button
    mat-raised-button
    color="primary"
    (click)="changePassword()"
    [disabled]="passwordChangeForm.invalid"
  >
    Change Password
  </button>
</div>

答案 7 :(得分:0)

如果您不想通过自定义验证器,则可以创建一个独立的输入字段,因此不会在formGroup中进行计算,而是通过ngModel

<input type="password" matInput [(ngModel)]="passwordConfirm" [ngModelOptions]="{standalone: true}">

然后在ts中,您可以根据需要验证并抛出错误或使表单无效。刚刚发现它更快,更实用:

//检查密码是否匹配

  if (this.staffAccountForm.value.password !== this.passwordConfirm) {
    this.snackbar.snackBarSimple('Passwords do not match.');
    return false;
  }

答案 8 :(得分:0)

对于那些想要添加自定义验证器而不被迫通过表单组验证的人,可以在定义表单后添加验证器。

此方法的一个优点是将错误添加到了表单控件而不是表单组中。这样,由于我们可以直接在字段/表单控件本身上检查错误,因此更容易显示与字段相关的错误。

这是我的实现方式:

自定义验证器

import { AbstractControl, ValidatorFn } from '@angular/forms';

export class MismatchValidator {

  static mismatch(otherInputControl: AbstractControl): ValidatorFn {

    return (inputControl: AbstractControl): { [key: string]: boolean } | null => {
      if (inputControl.value !== undefined
        && inputControl.value.trim() != ""
        && inputControl.value !== otherInputControl.value) {
        return { 'mismatch': true };
      }

      return null;
    };
  }
}

将自定义验证器应用于表单控件

  ngOnInit() {
    this.initForm();
    // The validators are set after defining the form in order to be able to access the password control and pass it to the custom validator as a parameter
    this.setValidators();
  }

  private initForm() {
    this.myForm = this.formBuilder.group({
      password: new FormControl(''),
      passwordConfirmation: new FormControl('')
    });
  }

  private setValidators() {
    const formValidators = {
      "password": Validators.compose([
        Validators.required,
        //....
      ]),
      "passwordConfirmation": Validators.compose([
        Validators.required,
        MismatchValidator.mismatch(this.myForm.get("password")) 
      ])
    }

    this.passwordRecoveryForm.get("password").setValidators(
      formValidators["password"]
    );
    this.passwordRecoveryForm.get("passwordConfirmation").setValidators(
      formValidators["passwordConfirmation"]
    );
  }

在定义表单之后设置验证器,以便能够访问密码控件并将其作为参数传递给自定义验证器。