MST

星途 面试题库

面试题:Angular中自定义表单验证规则及跨字段验证实现

在Angular应用里,有一个注册表单,其中包含密码和确认密码两个字段。要求自定义一个验证规则,确保两次输入的密码一致,并且当其中一个字段失去焦点时就触发验证,同时要在模板驱动表单和响应式表单中分别实现此功能,阐述实现思路并给出关键代码片段。
37.6万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

模板驱动表单

  1. 实现思路
    • 使用ngModel指令来双向绑定密码和确认密码输入框的值。
    • 创建一个自定义验证器函数,该函数接收AbstractControl并检查密码和确认密码是否一致。
    • 将自定义验证器添加到确认密码输入框的ngModel上。
    • 利用(blur)事件在字段失去焦点时触发验证。
  2. 关键代码片段
    • 自定义验证器(在validators.ts中)
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function passwordMatchValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const password = control.get('password');
    const confirmPassword = control.get('confirmPassword');
    return password && confirmPassword && password.value!== confirmPassword.value
     ? { passwordMismatch: true }
      : null;
  };
}
  • 模板代码(register.component.html
<form #registerForm="ngForm" (ngSubmit)="onSubmit(registerForm.value)">
  <div class="form-group">
    <label for="password">Password</label>
    <input type="password" id="password" name="password" [(ngModel)]="user.password" required>
  </div>
  <div class="form-group">
    <label for="confirmPassword">Confirm Password</label>
    <input type="password" id="confirmPassword" name="confirmPassword" [(ngModel)]="user.confirmPassword" required
      (blur)="registerForm.control.updateValueAndValidity()"
      [ngModelOptions]="{ standalone: true }"
      [validators]="[passwordMatchValidator()]">
    <div *ngIf="registerForm.controls.confirmPassword.hasError('passwordMismatch') && (registerForm.controls.confirmPassword.touched || registerForm.controls.confirmPassword.dirty)">
      Passwords do not match.
    </div>
  </div>
  <button type="submit" class="btn btn-primary">Register</button>
</form>
  • 组件代码(register.component.ts
import { Component } from '@angular/core';
import { passwordMatchValidator } from './validators';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.css']
})
export class RegisterComponent {
  user = { password: '', confirmPassword: '' };

  onSubmit(formData: any) {
    console.log(formData);
  }
}

响应式表单

  1. 实现思路
    • 使用FormGroupFormControl创建响应式表单。
    • 创建自定义验证器函数并添加到确认密码的FormControl中。
    • 使用valueChangesstatusChanges结合debounceTime等操作符在字段失去焦点时触发验证。
  2. 关键代码片段
    • 自定义验证器(在validators.ts中)
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function passwordMatchValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const password = control.get('password');
    const confirmPassword = control.get('confirmPassword');
    return password && confirmPassword && password.value!== confirmPassword.value
     ? { passwordMismatch: true }
      : null;
  };
}
  • 组件代码(register.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { passwordMatchValidator } from './validators';
import { debounceTime } from 'rxjs/operators';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.css']
})
export class RegisterComponent {
  registerForm: FormGroup;

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

    this.registerForm.get('password').valueChanges.pipe(
      debounceTime(300)
    ).subscribe(() => {
      this.registerForm.get('confirmPassword').updateValueAndValidity();
    });

    this.registerForm.get('confirmPassword').valueChanges.pipe(
      debounceTime(300)
    ).subscribe(() => {
      this.registerForm.get('confirmPassword').updateValueAndValidity();
    });
  }
}
  • 模板代码(register.component.html
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
  <div class="form-group">
    <label for="password">Password</label>
    <input type="password" id="password" formControlName="password">
  </div>
  <div class="form-group">
    <label for="confirmPassword">Confirm Password</label>
    <input type="password" id="confirmPassword" formControlName="confirmPassword">
    <div *ngIf="registerForm.get('confirmPassword').hasError('passwordMismatch') && (registerForm.get('confirmPassword').touched || registerForm.get('confirmPassword').dirty)">
      Passwords do not match.
    </div>
  </div>
  <button type="submit" class="btn btn-primary">Register</button>
</form>
  • 组件中的onSubmit方法(可自行补充逻辑)
onSubmit() {
  if (this.registerForm.valid) {
    console.log(this.registerForm.value);
  }
}