Angular 11 个表单确认密码字段,无需创建 formGroup 或使用 formBuilder

Angular 11 forms confirm password field without making a formGroup or using formBuilder

HTML 一组密码和确认密码表单字段:

  <mat-form-field>
    <mat-label>{{ 'PAGES.LOGIN.PASSWORD' | translate }}</mat-label>
    <input #registerPasswordField matInput title=" " [type]="hide ? 'password' : 'text'" [formControl]="password" required (keyup.enter)="registerConfirmField.focus()">
    <button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
      <mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
    </button>
    <mat-error *ngIf="password.invalid && password.errors?.pattern">{{ 'PAGES.REGISTER.PASSWORD_INVALID' | translate }}</mat-error>
    <mat-error *ngIf="password.invalid && !password.errors?.pattern">{{ 'PAGES.LOGIN.PASSWORD_REQUIRED' | translate }}</mat-error>
  </mat-form-field>
  <mat-form-field>
    <mat-label>{{ 'PAGES.REGISTER.CONFIRM' | translate }}</mat-label>
    <input #registerConfirmField matInput title=" " [type]="hide ? 'password' : 'text'" [formControl]="confirmPassword" required (keyup.enter)="loginButton.focus(); register()">
    <button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
      <mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
    </button>
    <mat-error *ngIf="confirmPassword.errors?.pattern">{{ 'PAGES.REGISTER.CONFIRM_MISMATCH' | translate }}</mat-error>
    <mat-error *ngIf="confirmPassword.invalid">{{ 'PAGES.REGISTER.CONFIRM_REQUIRED' | translate }}</mat-error>
  </mat-form-field>

使用以下 TS 端表单字段声明:

password = new FormControl("", [
    Validators.required,
    Validators.pattern("^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{8,255})\S$")
])
confirmPassword = new FormControl("", [
    Validators.required,
    confirmEquals(this, this.password) //pseudocode, obviously this won't work
])

我正在尝试为此做一些事情,我只是检查 password.value 和 confirmPassword.value 之间的相等。

我无法使用 Validators.pattern() 执行此操作(我不明白为什么 Validators.pattern(this.password.value) 不起作用。文档说它还接受一个字符串,在这种情况下,它在前面附加 ^ 并在后面附加 $,基本上它只对那个字符串进行正则表达式。它应该工作。但是这个验证器永远不会被触发)

我已经看到大量关于密码确认问题的 Whosebug 问题,但 none 对我来说似乎干净或简洁(但最重要的是最新的)。

我找到了这个旧的已弃用代码示例:

ngOnInit() {
    this.registerForm = this.formBuilder.group({
        firstName: ['', Validators.required],
        lastName: ['', Validators.required],
        email: ['', [Validators.required, Validators.email]],
        password: ['', [Validators.required, Validators.minLength(6)]],
        confirmPassword: ['', Validators.required]
    }, {
        validator: MustMatch('password', 'confirmPassword')
    });
}

这表明 angular 曾经费心去实现一个功能来达到这个效果。

但据我所知,它还没有移到新的 AbstractControl CLASS

字段“验证器”存在于 FormGroup 的新语法中,但我更喜欢更新的语法,其中您不声明整个表单而只声明每个字段,如新 [=56= 中所示]-material 文档。

现在似乎不鼓励使用 FormBuilder

我希望我的方法是 KISS 和高效的,并且语法简洁。

是否可以在不将两个 formControl 放在一个公共 formGroup 下的情况下进行密码确认(以干净、现代的方式)?

我承认这是一个糟糕的方法,但我想知道为什么以及“Angular 11”的做法是什么(答案需要与当前最佳实践)。

编辑:我一直在读这个:

以及对此的评论:

但我现在必须创建自己的注册。

有了 custom validator 你可以做到。试试看,

app.component.ts

  password = new FormControl("", [
    Validators.required,
    Validators.pattern(
      "^((?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9]).{8,255})\S$"
    )
  ]);
  confirmPassword = new FormControl("", [
    Validators.required,
    this.confirmEquals() 
  ]); 

  confirmEquals(): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } | null =>  
        control.value?.toLowerCase() === this.passwordValue.toLowerCase() 
            ? null : {noMatch: true};
  }

  get passwordValue() {
    return this.password.value;
  }

app.component.html

    <mat-form-field class="example-full-width">
        <input matInput placeholder="Password" [formControl]="password"/>
        <mat-error *ngIf="password.dirty && password.errors?.pattern">
            <strong>Pattern Wrong</strong>
        </mat-error>
    </mat-form-field>
    <mat-form-field class="example-full-width">
        <input matInput placeholder="Confirm Password" [formControl]="confirmPassword"/>
        <mat-error *ngIf="confirmPassword.dirty && confirmPassword.errors?.noMatch">
            <strong>Password</strong> and <strong>Confirm Password</strong> must be same
        </mat-error>
    </mat-form-field>

工作 stackblitz 示例:https://stackblitz.com/edit/angular-ztqtaz?file=src/app/app.component.html

希望这对您有所帮助:)