Search code examples
angularobservableangular-validation

Async validator causes the form status to stay PENDING


EDIT: The switchmap seems to be the culprit. When removing it, the status of my form does no longer stay stuck in Pending. Can anyone explain this ?

I am using the following factory to create async validators for my forms:

export function createAsyncValidator(checkFn: (value: string) => Observable<Boolean>, errorMessage: string) {
    return (control: AbstractControl): Observable<ValidationErrors> => {
        return Observable.timer(500).switchMap(() => {
            return checkFn(control.value)
                .map(result => {
                    return result ? null : { [errorMessage]: true };
                });
        });
    };
}

I add it to my form like this:

createAsyncValidator(this.asyncValidator, 'Error')

Implementation of the validator (example):

asyncValidator = (value: string): Observable<Boolean> => {
    if (value === 'test') {
        return Observable.of(true); // THIS CAUSES THE FORM TO BE PENDING
    }    
    return this.http.get('url/'  + value, true); // THIS WORKS
};

When my async validator uses a http call to validate my input, everything works as expected. However, if I return with Observable.of(true), the whole form stays in PENDING

After some research I figured that my Observable is not complete, hence the state PENDING. How can I return an observable that completes ?


Solution

  • Replacing the switchMap with a flatMap sovles my problem:

    export function createAsyncValidator(checkFn: (value: string) => Observable<Boolean>, errorMessage: string) {
        return (control: AbstractControl): Observable<ValidationErrors> => {
            return Observable.timer(500).flatMap(() => {
                return checkFn(control.value)
                    .map(result => {
                        return result ? null : { [errorMessage]: true };
                    });
            });
        };
    }