表单控制异步验证问题

时间:2019-12-06 21:34:36

标签: angular observable angular2-observables

我正在尝试对angular2进行异步验证,但是当我出于某种原因尝试输入某些内容时,反跳功能将无法正常工作。它会根据我的输入多次触发。同样在加载时,我的异步验证器也会被触发,因此将状态设置为待定,因此信息框显示checking...

这是我的实现方式:

HTML:

 <div class="form-group d-flex col px-0">
   <label for="coupon" class="col-2">coupon_code:</label
    <div class="col-5 pl-4 pr-0">
     <input
      class="form-control"
      id="coupon"
      type="text"
      name="coupon"
      formControlName="coupon"
      autocomplete="off"
      />
 </div>

TS文件

表格:

initForm() {
    const email = '';
    const password = '';
    const password_confirmation = '';
    const doctor = '';
    // const license = '';
    const type = 'doctor';
    const company_id = '';
    const corporate_token = '';
    const doctorLastName = '';

    this.signUpForm = this.fb.group(
      {
        coupon: ['',[], this.couponAsyncValidation.bind(this)]
      },
      {
        validator: this.signupFormValidator(),
      }
    );
  }

异步验证码:

 couponAsyncValidation(control: FormControl): Promise<any | null> | Observable<any | null> {
     return new Promise( (res, rej) => {
      control.valueChanges.pipe(
        debounceTime(2000),
        distinctUntilChanged(),
        switchMap(value => this.userService.couponChecker(value)),
        map( (q) => q ),
        first()
      ).subscribe(
        (d) => { 
        console.log(d)
         d.is_coupon_valid ? res(null) : res({invalid: true})
        }
      )
    })
  }

couponAsyncValidation将在加载时被触发,即使我没有触摸输入,状态也仍处于待处理状态。疯了

更新 管理工作状态。我已经检查了状态和未决状态以及是否脏了。

剩下的问题是debounceTimer无法正常工作

更新 我认为我缺少可观察的功能。你觉得怎么样?

更新 这是2秒后发送的请求的图片

enter image description here

你知道为什么去抖不起作用吗?

更新

这是在@jarek的帮助下进行的。

这是异步验证的完整代码


import { AbstractControl, AsyncValidatorFn } from '@angular/forms';
import { switchMap, map} from 'rxjs/operators';
import { UserService } from '../user/services/user.service';
import { Observable, timer, of } from 'rxjs';

export class AsyncValidator {
  static couponValidator(miliSec: number, service: UserService): AsyncValidatorFn {
    return (control: AbstractControl): Observable<any | null> => {
      return timer(miliSec).pipe(
        switchMap(() => {
          if ( control.value ) {
            return service.couponChecker(control.value);
          }
          // this one is needed because for some reason on loading, the signup page
          // will immediately trigger this async call which sends a request to the backend
          // even though user has not inputted anything.
          // then sets the status of the form to pending thus resulting to an invalid form
          return of({is_coupon_valid: true});
        }),
        map( (res) =>  res.is_coupon_valid ? null : res )
      );
    };
  }
}

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

我有一个类似的情况,除了我的异步验证器直接在表单上...代码在下面,但它与您所需的内容不完全匹配。我怀疑您的核心问题是您的订阅控制值更改是不必要的,因为将其设置为验证器应该已经使该验证器在值更改时被调用。

validateExists(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
{
    return timer(500).pipe(
            switchMap(() =>
                this.service.checkThingExists(control.value.value1, control.value.value2).pipe(
                    tap(() => setTimeout(() => this.isValid.emit(this.form.get('parcel').valid))),
                    map(valid => (valid ? null : { notFound: true }))
                )
            )
        );
}