Angular 异步验证器检查数据库中输入的唯一性

Angular async validator check unicity of input in database

我有一个 <input>,用户可以在其中输入一个在数据库中应该是唯一的值。我想在前端动态检查该值是否唯一。

如果该值已存储在数据库中,我还想显示一条错误消息。

您可以使用自定义异步验证器来做到这一点。假设您要检查名称是否唯一。首先,为异步验证器创建一个新文件:

@Injectable({ providedIn: 'root' })
export class NameValidator {

    constructor(private nameService: NameService) { }

    CheckNameValidator(): AsyncValidatorFn {
        return (control: AbstractControl): Observable<{ [key: string]: boolean } | null> => {
            return this.nameService.nameExists(control.value)
                .pipe(
                    map(valueExists => {
                        if (valueExists) {
                            return { nameExists: true };
                        }
                        return null;
                    }
                    )
                )
        }
    }

验证器是一种服务,您可以在其中导入服务名称服务,您可以在其中调用您的 api。无论值是否存在,api 必须 return。然后,在控制器中:


export class MainComponent implements OnInit {

  constructor(
    private fb: FormBuilder,
    private nameValidator: NameValidator 
    ) {}

public formGroup: FormGroup;

ngOnInit(): void { 
  
    this.formGroup = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(3)], [this.nameValidator.CheckNameValidator()]]
    }, {updateOn: 'blur'});
  }

构建表单组时,每个表单控件都可以包含一个值、一个验证器数组和一个异步验证器数组。那就是我调用异步验证器服务的地方。

注意 {updateOn: 'blur'},如果你不写这个,检查验证器的更新正在更改,所以你进行了太多的 api 调用。使用 onBlur,api 调用完成 onblur => 性能提升。

如果您使用 angular material,您的视图应如下所示:

<ng-container [formGroup]="formGroup">
    <mat-form-field class="field-full-width">
        <input matInput placeholder="Name" formControlName="name">
        <mat-error *ngIf="formGroup.controls['name'].errors?.nameExists">This name is already in use</mat-error>
    </mat-form-field>
</ng-container>