How to add debounce time to an async validator in angular 2? How to add debounce time to an async validator in angular 2? angular angular

How to add debounce time to an async validator in angular 2?


Angular 4+, Using Observable.timer(debounceTime) :

@izupet 's answer is right but it is worth noticing that it is even simpler when you use Observable:

emailAvailability(control: Control) {    return Observable.timer(500).switchMap(()=>{      return this._service.checkEmail({email: control.value})        .mapTo(null)        .catch(err=>Observable.of({availability: true}));    });}

Since angular 4 has been released, if a new value is sent for checking, Angular unsubscribes from Observable while it's still paused in the timer, so you don't actually need to manage the setTimeout/clearTimeout logic by yourself.

Using timer and Angular's async validator behavior we have recreated RxJS debounceTime.


Keep it simple: no timeout, no delay, no custom Observable

// assign the async validator to a fieldthis.cardAccountNumber.setAsyncValidators(this.uniqueCardAccountValidatorFn());// or like thisnew FormControl('', [], [ this.uniqueCardAccountValidator() ]);
// subscribe to control.valueChanges and define pipeuniqueCardAccountValidatorFn(): AsyncValidatorFn {  return control => control.valueChanges    .pipe(      debounceTime(400),      distinctUntilChanged(),      switchMap(value => this.customerService.isCardAccountUnique(value)),      map((unique: boolean) => (unique ? null : {'cardAccountNumberUniquenessViolated': true})),      first()); // important to make observable finite}


It is actually pretty simple to achieve this (it is not for your case but it is general example)

private emailTimeout;emailAvailability(control: Control) {    clearTimeout(this.emailTimeout);    return new Promise((resolve, reject) => {        this.emailTimeout = setTimeout(() => {            this._service.checkEmail({email: control.value})                .subscribe(                    response    => resolve(null),                    error       => resolve({availability: true}));        }, 600);    });}