自定义验证器无法在 Angular 响应式表单中工作

Custom Validator Not Working in Angular Reactive Form

我正在尝试创建一个自定义验证器来检查 phone 号码是否已经存在。 我的代码如下:

验证函数

phoneValidator() {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      if (!control.valueChanges || control.pristine) {
        return of(null);
      } else {
        this.userMgt.phoneExists(control.value).pipe(
          distinctUntilChanged(),
          debounceTime(600))
          .subscribe((res: ApiResponse<any>) => {
            debugger
            if(!res.hasErrors()) {
              if(res.data == true) {
                return { phoneExists: true };
              }
              else {
                return null
              }
            }
        })
      }
    };
  }

后端验证phone号码的API:

phoneExists(phoneNo: string): Observable<ApiResponse<user>> {
        return this.clubApiGet(`/profile/isPhoneNumberExists?phoneNo=${phoneNo}`)
    }

我的表单组

private fb: FormBuilder,
defaultUser: User = {
    phoneNo: ""
  };

ngOnInit(): void {
    this.initUserForm();
  }

initUserForm() {
    this.userForm = this.fb.group({
      phone: [
        this.defaultUser.phoneNo,
        Validators.compose([
          Validators.required,
          Validators.minLength(11),
          Validators.maxLength(14),
          this.phoneValidator()
        ]),
      ]
    });
  }

我的HTML

<div class="form-group row">
  <label class="col-xl-3 col-lg-3 col-form-label">Contact Phone
    <span class="text-danger">*</span>
  </label>
<div class="col-lg-9 col-xl-6">
  <div class="input-group input-group-lg input-group-solid">
     <div class="input-group-prepend">
      <span class="input-group-text">
       <i class="fas fa-phone-alt text-primary"></i>
      </span>
     </div>
     <input
       type="text"
       class="form-control form-control-lg form-control-solid"
       value="+35278953712"
       placeholder="Phone"
       formControlName="phone"
       [ngClass]="{ 'is-in valid': userForm.controls['phone'].invalid&& 
       userForm.controls['phone'].errors}"
      >
</div>
<ng-container [ngTemplateOutlet]="formError" [ngTemplateOutletContext]="{
    validation: 'required',
    message: 'Phone Number is required',
    control: userForm.controls['phone']
}"></ng-container>

<ng-container [ngTemplateOutlet]="formError" [ngTemplateOutletContext]="{
    validation: 'minlength',
    message: 'Phone Number should at least be 11 characters',
    control: userForm.controls['phone']
}"</ng-container>

<ng-container [ngTemplateOutlet]="formError" [ngTemplateOutletContext]="{
    validation: 'maxlength',
    message: 'Phone Number cannot exceed 14 characters',
    control: userForm.controls['phone']
}"</ng-container>

// THIS VALIDATION CHECK DOES NOT WORK
<div class="text-danger" *ngIf="userForm.controls['phone']?.errors?.phoneExists">
   This Phone Number is already registered to a user
</div>
</div>
</div>

我想不通问题出在哪里。 API 工作正常,但未显示错误消息。我真的很感激任何帮助。谢谢!

  • 您已添加 this.phoneValidator() 作为同步验证器的一部分。它应该是异步验证器的一部分:
phone: [
  this.defaultUser.phoneNo,
  Validators.compose([
    Validators.required,
    Validators.minLength(11),
    Validators.maxLength(14)
  ]),
  [this.phoneValidator()]
]
  • 您不需要订阅,而是 return 来自异步验证器函数的 Observable:
// else block 
return this.userMgt.phoneExists(control.value).pipe(  // added 'return'
  distinctUntilChanged(),
  debounceTime(600),
  map((res: ApiResponse<any>) => { // using map operator
    debugger
    if (!res.hasErrors()) {
      if (res.data == true) {
        return { phoneExists: true };
      }
      else {
        return null
      }
    }
    return null; // added return statement
  })
);