Angular 表单验证:显示空密码和不匹配密码的错误

问题描述 投票:0回答:1

我想执行表单验证。如果该字段“脏”。

  1. 如果密码字段中没有任何内容,则会显示错误。

  2. 如果密码不匹配,也应该显示错误。

你能向我解释一下我的代码有什么问题吗?我已经创建了一个代码示例:

https://stackblitz.com/edit/stackblitz-starters-wtwfd8?file=src%2Fmain.ts

我使用 Angular 17 和 Angular Material。

angular angular-material angular-forms
1个回答
0
投票

我们可以使用

?.
打字稿安全运算符来防止访问属性时 html 中出现任何错误。注意事项:

  1. 我们已经在表单级别设置了
    mismatch
    验证器进行验证,但是我们在确认密码表单字段处显示了错误消息,因此我们需要通知表单控件该元素处于错误状态,为此我们可以使用
    errorStateMatcher
    输入绑定来更新表单,这将显示错误!

错误状态匹配器代码!

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(
    control: FormControl | null,
    form: FormGroupDirective | NgForm | null
  ): boolean {
    return !!(form?.errors?.['mismatch'] && form?.touched);
  }
}
...

...
export class App {
  name = 'Angular';
  registerForm: FormGroup;
  matcher = new MyErrorStateMatcher();

html

...
<input matInput formControlName="confirmPassword" type="password" [errorStateMatcher]="matcher"> 
...
  1. 我们可以使用
    @switch
    代替
    @if
    ,因为我们通常一次显示一个错误,所以如果我们使用
    switch
  2. ,代码会更少

请找到下面的完整代码和工作 stackblitz 以供参考!

完整代码:

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import {
  AbstractControl,
  FormControl,
  FormGroup,
  NgForm,
  ReactiveFormsModule,
  Validators,
  FormGroupDirective,
} from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule } from '@angular/forms';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { CommonModule } from '@angular/common';
import { ErrorStateMatcher } from '@angular/material/core';

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(
    control: FormControl | null,
    form: FormGroupDirective | NgForm | null
  ): boolean {
    return !!(form?.errors?.['mismatch'] && form?.touched);
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    ReactiveFormsModule,
    MatInputModule,
    MatFormFieldModule,
    MatCheckboxModule,
    MatButtonModule,
    FormsModule,
    CommonModule,
  ],
  template: `
    <form [formGroup]="registerForm">
      <mat-form-field>
          <mat-label>Password</mat-label>
          <input matInput formControlName="password" type="password"> 
          @if (registerForm?.get('password')?.touched) {
            <mat-error>
            @switch (true) {
                @case (registerForm.get('password')?.hasError('required')) {
                  Password is required
                }
                @case (registerForm.get('password')?.hasError('minlength')) {
                  Password must be 6 characters in length
                }
            }
          </mat-error>
          }
      </mat-form-field>

      <mat-form-field>
          <mat-label>Confirm Password</mat-label>
          <input matInput formControlName="confirmPassword" type="password" [errorStateMatcher]="matcher"> 
          @if (registerForm?.get('confirmPassword')?.touched) {
            <mat-error>
            @switch (true) {
                @case (registerForm.get('confirmPassword')?.hasError('required')) {
                  Confirm Password is required
                }
                @case (registerForm.errors?.['mismatch']) {
                  Password does not match
                }
            }
          </mat-error>
          }
      </mat-form-field>


      <button mat-raised-button color="primary " type="submit" [disabled]="!registerForm.valid">Sign up</button>
</form>
  `,
})
export class App {
  name = 'Angular';
  registerForm: FormGroup;
  matcher = new MyErrorStateMatcher();

  constructor() {
    this.registerForm = new FormGroup(
      {
        password: new FormControl('', [
          Validators.required,
          Validators.minLength(6),
        ]),
        confirmPassword: new FormControl('', [Validators.required]),
      },
      { validators: this.passwordMatchValidator }
    );
  }

  private passwordMatchValidator(control: AbstractControl) {
    return control.get('password')?.value ===
      control.get('confirmPassword')?.value
      ? null
      : { mismatch: true };
  }
}

bootstrapApplication(App, {
  providers: [provideAnimationsAsync()],
});

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.