custom async validation not working when returning

2019-02-18 08:14发布

问题:

I'm calling the web api to check if an urlalias is available, for this task I'm using a httpservice in my async validator. The issue is that when the validator is called, all the correct code path is performed (all the console.log() run and behave as expected).

Whether the promise from the validation returns/resolves to null or an { 'isUrlAliasActivityMainAvailable': true }, the controller always shows an error object as following, thus keeping the form state as invalid, why (bloody hell!)?

I'm using: angular:2.1.0 and rxjs:5.0.0-beta.12

This is my formbuilder:

this.formBuilder.group({
//...
"urlAliasActivityMain":[null,[ ValidatorsZr.isUrlAliasActivityMainAvailableAsyncValidator(this.httpActivityService)]],
});

This is my validator:

   public static isUrlAliasActivityMainAvailableAsyncValidator(httpActivityService: HttpActivityService) {
        return function (control: FormControl): Promise<any> | Observable<any> {

            const promise = new Promise<any>(
                (resolve, reject) => {
                    httpActivityService.isUrlAliasActivityMainAvailable(control.value)
                        .subscribe(
                        (data: any) => {
                            console.log("isUrlAliasActivityMainAvailableAsyncValidator");
                            console.log(data);
                            if (data == false) {
                                console.log("data == false");
                                resolve({ 'isUrlAliasActivityMainAvailable': true });
                            }
                            else {
                                console.log("data == true");
                                resolve(null);
                            }
                        },

                    )
                });

            return promise;
        }
    }

回答1:

Your async validator is listed in the synchronous validators location in the array and is being incorrectly evaluated.

[objectValue, synchronous validators, asynchronous validators]

control(formState: Object, validator?: ValidatorFn|ValidatorFn[], asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]) : FormControl Construct a new FormControl with the given formState,validator, and asyncValidator.

formState can either be a standalone value for the form control or an object that contains both a value and a disabled status.

To correct it, move your validator to the appropriate array location:

this.formBuilder.group({
//...
"urlAliasActivityMain":[null, null, ValidatorsZr.isUrlAliasActivityMainAvailableAsyncValidator(this.httpActivityService)],
});