angular 中的密码确认验证 - 奇怪的行为

password confirm validation in angular - strange behaviour

我在 Angular 中使用自定义验证器实现了确认密码验证。这是自定义验证器 class:

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

export class Validation {
  static match(controlName: string, checkControlName: string): ValidatorFn {
    return (controls: AbstractControl) => {
      const control = controls.get(controlName);
      const checkControl = controls.get(checkControlName);

      if (checkControl?.errors && !checkControl.errors.matching) {
        return null;
      }

      if (control?.value !== checkControl?.value) {
        controls?.get(checkControlName)?.setErrors({ matching: true });
        return { matching: true };
      } else {
        return null;
      }
    };
  }
}

我使用反应式,这是我构建它的方式:

initSignupForm() {
    this.signupForm = new FormGroup(
      {
        email: new FormControl(this.formData.email, [
          Validators.required,
          Validators.email,
        ]),
        password: new FormControl(this.formData.password, [
          Validators.required,
        ]),
        passwordConfirm: new FormControl(this.formData.passwordConfirm, [
          Validators.required,
        ]),
      },
      { validators: [Validation.match('password', 'passwordConfirm')] }
    );
  }

这是组件 html:

<div class="card">
  <kendo-card width="320px">
    <h2>Regisztráció</h2>
    <form [formGroup]="signupForm">
      <kendo-formfield>
        <kendo-textbox placeholder="E-mail cím" formControlName="email">
          <ng-template kendoTextBoxPrefixTemplate>
            <kendo-svg-icon [icon]="icons.user"></kendo-svg-icon>
            <div id="empty-div"></div>
          </ng-template>
        </kendo-textbox>
        <kendo-formerror *ngIf="signupForm.controls.email.errors?.required"
          >Kötelező mező</kendo-formerror
        >
        <kendo-formerror *ngIf="signupForm.controls.email.errors?.email"
          >Hibás e-mail formátum</kendo-formerror
        >
      </kendo-formfield>
      <kendo-formfield>
        <kendo-textbox
          placeholder="Jelszó"
          #tbxPassword
          formControlName="password"
        >
          <ng-template kendoTextBoxPrefixTemplate>
            <button
              id="tbxPassword"
              kendoButton
              icon="eye"
              (click)="togglePass()"
            ></button>
          </ng-template>
        </kendo-textbox>
        <kendo-formerror>Kötelező mező</kendo-formerror>
      </kendo-formfield>
      <kendo-formfield>
        <kendo-textbox
          placeholder="Jelszó még egyszer"
          #tbxRepeatPassword
          formControlName="passwordConfirm"
        >
          <ng-template kendoTextBoxPrefixTemplate>
            <button kendoButton icon="eye" (click)="togglePassRep()"></button>
          </ng-template>
        </kendo-textbox>
        <kendo-formerror
          *ngIf="signupForm.controls.passwordConfirm.errors?.required"
          >Kötelező mező</kendo-formerror
        >
        <kendo-formerror *ngIf="signupForm.errors?.matching"
          >A két jelszó nem egyezik</kendo-formerror
        >
      </kendo-formfield>
      <button class="btn" kendoButton [primary]="true" (click)="submitForm()">
        ÚJ FIÓK LÉTREHOZÁSA
      </button>
      <div class="link">
        <span>Már van fiókod? </span>
        <a href="#" (click)="backToLogin()">Jelentkezz be</a>
      </div>
    </form>
  </kendo-card>
  <lang-selector></lang-selector>
</div>

它有效,但有以下副作用。 F. e.如果我在密码字段中键入 'a',然后在确认密码字段中键入 'b',我会收到错误消息。美好的。现在,如果我将 'b' 更改为 'a',错误消息消失,可以提交表单。美好的。但是,如果我将第一个密码('a')更改为'b',错误消息也会消失,但确认密码字段仍然是红色,我无法提交表单。表单本身没有更多的错误(我已经在控制台中检查过了),但是字段本身仍然有这个 matching 错误。这是为什么?

这是因为您在 passwordConfirm 控件上手动设置错误,但您正在检查表单本身的错误以显示错误消息。由于 passwordConfirm 的值未更改,因此未清除错误列表。

这意味着错误将不会显示(因为您的验证器 return 为 null)但表单无效(因为 passwordConfirm 仍然存在错误)。

因此,您要么必须删除在控件本身上设置错误的行 (controls?.get(checkControlName)?.setErrors({ matching: true });),要么确保在验证器的每次评估中都将错误添加到或删除数组存在错误。

问题就在这里Validation.match

controls?.get(checkControlName)?.setErrors({ matching: true });

您正在 checkControlName 上手动设置验证,但它应该在 formGroup 上。由于某种原因,验证混淆了,这导致了意外的验证。我试图找出场景,但没能找到它。

解决您的问题。

删除 controls?.get(checkControlName)?.setErrors({ matching: true }); 里面的 if (control?.value !== checkControl?.value)

在 component.ts 中的 getter 下方添加: - 获取 FormGroup,以便我们可以在我们的模板中使用它进行验证。

get fg(): FormGroup {
    return this.signupForm as FormGroup;
}

改变

<kendo-formerror *ngIf="signupForm.errors?.matching">
    A két jelszó nem egyezik
</kendo-formerror>

<kendo-formerror *ngIf="fg.hasError('matching')">
    A két jelszó nem egyezik
</kendo-formerror>

就是这样:Similar Demo