MST
星途 面试题库

面试题:Angular自定义验证器与异步验证及错误处理的深度结合

在Angular应用中,要求创建一个自定义异步验证器,用于验证用户名是否已存在(通过后端API查询)。同时,当验证失败时,需要以用户友好的方式显示错误信息,并考虑在不同场景下(如表单提交、输入变化等)的错误处理和显示逻辑。请阐述完整的实现方案及关键代码。
13.1万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

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

在Angular中,自定义异步验证器是一个返回ObservablePromise的函数。这个函数接收一个AbstractControl参数,用于获取输入控件的值,并进行验证。

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

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

  validate(control: AbstractControl): Observable<ValidationErrors | null> {
    const username = control.value;
    return this.http.get<any>(`/api/check-username/${username}`).pipe(
      map(response => {
        if (response.exists) {
          return { usernameExists: true };
        }
        return null;
      })
    );
  }
}

2. 在模块中注册验证器

NgModuleproviders数组中注册自定义异步验证器。

import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform - browser';

import { AppComponent } from './app.component';
import { UsernameExistsValidator } from './username - exists.validator';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule, ReactiveFormsModule],
  providers: [
    {
      provide: NG_ASYNC_VALIDATORS,
      useExisting: UsernameExistsValidator,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

3. 在表单中使用验证器

ReactiveFormsModule中,可以将自定义异步验证器添加到FormControl中。

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

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

  constructor() {
    this.myForm = new FormGroup({
      username: new FormControl('', [Validators.required], [this.usernameExistsValidator.validate])
    });
  }

  get username() {
    return this.myForm.get('username');
  }
}

4. 显示错误信息

在模板中,可以根据验证结果显示用户友好的错误信息。

<form [formGroup]="myForm">
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" formControlName="username">
    <div *ngIf="username.hasError('required') && (username.touched || myForm.submitted)">
      Username is required.
    </div>
    <div *ngIf="username.hasError('usernameExists') && (username.touched || myForm.submitted)">
      This username already exists. Please choose another one.
    </div>
  </div>
  <button type="submit">Submit</button>
</form>

不同场景下的错误处理和显示逻辑

  • 输入变化:当用户输入时,touched状态会改变,此时如果验证失败,错误信息会显示。例如,用户输入完用户名后,离开输入框,验证器会立即检查用户名是否存在,并显示相应错误信息。
  • 表单提交:当用户点击提交按钮时,myForm.submitted状态为true,此时无论输入框是否touched,都会检查验证状态并显示错误信息。这样可以确保用户在提交表单时,所有的验证错误都能被正确显示。