MST
星途 面试题库

面试题:Angular复杂表单的异步验证实现

假设在一个复杂的订单创建表单中,有一个商品编号输入框,需要在用户输入后通过后端接口验证该商品编号是否存在。请阐述如何在Angular中实现这种异步表单验证,包括在组件类和模板中的关键代码实现,以及如何处理验证过程中的加载状态和错误提示。
31.4万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

1. 创建异步验证器

在Angular中,可以创建一个自定义异步验证器函数。例如,创建一个productExistsValidator.ts文件:

import { AbstractControl, AsyncValidatorFn, ValidationErrors,  } from '@angular/forms';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

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

  createValidator(): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      const productId = control.value;
      if (!productId) {
        return of(null);
      }
      return this.http.get<any>(`/api/checkProductExists/${productId}`)
      .pipe(
          map(response => {
            return response.exists? null : { productDoesNotExist: true };
          }),
          catchError(() => of({ productDoesNotExist: true }))
        );
    };
  }
}

2. 在组件类中使用异步验证器

在组件类(例如order-create.component.ts)中导入并使用上述验证器:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ProductExistsValidator } from './productExistsValidator';

@Component({
  selector: 'app-order-create',
  templateUrl: './order-create.component.html',
  styleUrls: ['./order-create.component.css']
})
export class OrderCreateComponent {
  orderForm: FormGroup;
  isLoading = false;

  constructor(private productExistsValidator: ProductExistsValidator) {
    this.orderForm = new FormGroup({
      productId: new FormControl('', [Validators.required], this.productExistsValidator.createValidator())
    });

    this.orderForm.get('productId').statusChanges.subscribe(status => {
      if (status === 'PENDING') {
        this.isLoading = true;
      } else {
        this.isLoading = false;
      }
    });
  }
}

3. 在模板中显示加载状态和错误提示

在模板文件(例如order-create.component.html)中:

<form [formGroup]="orderForm">
  <div>
    <label for="productId">商品编号</label>
    <input type="text" id="productId" formControlName="productId">
    <div *ngIf="orderForm.get('productId').hasError('required') && (orderForm.get('productId').touched || orderForm.get('productId').dirty)">
      商品编号为必填项
    </div>
    <div *ngIf="isLoading && orderForm.get('productId').status === 'PENDING'">
      验证中...
    </div>
    <div *ngIf="orderForm.get('productId').hasError('productDoesNotExist') && (orderForm.get('productId').touched || orderForm.get('productId').dirty)">
      该商品编号不存在
    </div>
  </div>
</form>

总结

  1. 异步验证器创建:通过创建一个实现AsyncValidatorFn接口的函数,使用HttpClient发起HTTP请求验证商品编号是否存在。
  2. 组件类:在组件类中创建表单时,将异步验证器应用到对应的FormControl上,并通过监听statusChanges来处理加载状态。
  3. 模板:在模板中根据表单控件的状态和错误信息,显示加载状态和错误提示,提升用户体验。