1
votes

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 ?

1
The of operator creates an Observable that emits some values you specify as arguments, immediately one after the other, and then emits a complete notification. So I don't think the problem is with of... Does your code inside the map executes when the value is test? - Ritesh Waghela
The switchmap seems to be the culprit. When removing it, the status of my form does no longer stay stuck in Pending. - Tim

1 Answers

0
votes

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 };
                });
        });
    };
}