MST
星途 面试题库

面试题:Angular表单自定义异步验证器在用户输入邮箱时的应用

在Angular应用中,当用户输入邮箱后,需要验证该邮箱是否已在服务器端注册。请详细阐述如何创建一个自定义的异步验证器来实现此功能,包括如何在组件中定义异步验证逻辑以及在模板中如何应用该验证器,并处理验证过程中的加载状态和验证失败提示。
44.6万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

1. 创建自定义异步验证器

首先,创建一个用于异步验证邮箱是否已注册的服务。假设名为 EmailValidationService

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class EmailValidationService {
  constructor(private http: HttpClient) {}

  checkEmailExists(email: string): Observable<boolean> {
    // 假设后端接口为 /api/checkEmail,将邮箱作为参数传递
    return this.http.get<{ exists: boolean }>(`/api/checkEmail?email=${email}`)
     .pipe(
        map(response => response.exists)
      );
  }
}

然后,创建自定义异步验证器函数。在 validators 文件夹下创建 asyncEmailValidator.ts

import { AbstractControl, AsyncValidator, ValidationErrors, NG_ASYNC_VALIDATORS } from '@angular/forms';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { EmailValidationService } from './email-validation.service';

@Injectable({
  providedIn: 'root',
  // 将该验证器注册到 NG_ASYNC_VALIDATORS 中
  providers: [{
    provide: NG_ASYNC_VALIDATORS,
    useExisting: AsyncEmailValidator,
    multi: true
  }]
})
export class AsyncEmailValidator implements AsyncValidator {
  constructor(private emailValidationService: EmailValidationService) {}

  validate(control: AbstractControl): Observable<ValidationErrors | null> {
    return this.emailValidationService.checkEmailExists(control.value)
     .pipe(
        map((exists: boolean) => {
          return exists? { emailExists: true } : null;
        })
      );
  }
}

2. 在组件中定义异步验证逻辑

在组件的 ts 文件中,引入并使用该异步验证器:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { AsyncEmailValidator } from './validators/asyncEmailValidator';

@Component({
  selector: 'app-email-form',
  templateUrl: './email-form.component.html',
  styleUrls: ['./email-form.component.css']
})
export class EmailFormComponent {
  emailForm: FormGroup;
  isLoading = false;

  constructor(private asyncEmailValidator: AsyncEmailValidator) {
    this.emailForm = new FormGroup({
      email: new FormControl('', [Validators.required, Validators.email], this.asyncEmailValidator.validate.bind(this.asyncEmailValidator))
    });
  }

  onSubmit() {
    if (this.emailForm.valid) {
      // 处理表单提交逻辑
    }
  }
}

3. 在模板中应用验证器并处理加载状态和验证失败提示

在组件的模板文件(email-form.component.html)中:

<form [formGroup]="emailForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" formControlName="email">
    <div *ngIf="emailForm.get('email').hasError('required') && (emailForm.get('email').touched || emailForm.get('email').dirty)">
      Email is required.
    </div>
    <div *ngIf="emailForm.get('email').hasError('email') && (emailForm.get('email').touched || emailForm.get('email').dirty)">
      Please enter a valid email.
    </div>
    <div *ngIf="emailForm.get('email').hasError('emailExists') && (emailForm.get('email').touched || emailForm.get('email').dirty)">
      This email is already registered.
    </div>
    <div *ngIf="isLoading">Checking if email is registered...</div>
  </div>
  <button type="submit" [disabled]="emailForm.invalid || isLoading">Submit</button>
</form>

总结

通过上述步骤,我们创建了一个自定义的异步验证器来验证邮箱是否已在服务器端注册。在组件中正确地引入并使用了该验证器,并在模板中处理了验证过程中的加载状态和验证失败提示。这样,当用户输入邮箱时,系统会在服务器端验证邮箱的唯一性,并给出相应的提示。