Search code examples
angulartypescriptformbuildercustomvalidator

Validate a form field asynchronously (after HTTP request) in Angular 2


The idea is to let the user POST the form. And trigger the error returned by the API for set the email field as error if the user is already register.

I use reactive forms with FormBuilder and I trying calling the validator in the subscribe error catcher :

Constructor :

this.email = fb.control('', [Validators.required, Validators.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/), SignupComponent.alreadyExist()]);
this.username = fb.control('', [Validators.required, Validators.pattern(/^([A-ZÀ-ÿa-z0-9]{2,})+(?:[ _-][A-ZÀ-ÿa-z0-9]+)*$/)]);

this.userRegisterForm = fb.group({
    email: this.email,
    username: this.username
});

Custom alreadyExist() validator :

static alreadyExist(alreadyExist: boolean = false): any {

    return (control: FormControl): { [s: string]: boolean } => {

        if(alreadyExist) {
            return { emailAlreadyExist: true }
        }
    }
}

onSubmit() :

this.user.create(newUser)
    .subscribe(
        data => {
            this.router.navigate(['signin']);
        },
        error => {
            if(error.status === 401) {

                // CALL THE VALIDATOR HERE TO SET : FALSE
                SignupComponent.alreadyExist(true);
            }

            this.loading = false;
        });

It appear that the validator is called but the returned anonymous method inside it is never called... Maybe isn't a good practice, anyone can highlight me ? thx


Solution

  • Ok I found a good solution.

    In my case, for the email FormControl, I don't need a custom validator (even if is possible with setValidators()).

    I can delete alreadyExist() and remove its declaration from the list of validators.

    Then, I use setErrors() method available on FormControl :

    onSubmit() :

    this.user.create(newUser)
        .subscribe(
            data => {
                this.router.navigate(['signin']);
            },
            error => {
                if(error.status === 401) {
    
                    // CALL THE VALIDATOR HERE TO SET : FALSE
                    this.userRegisterForm.controls['email'].setErrors({
                      "emailAlreadyExist": true
                    });
                }
    
                this.loading = false;
            });
    

    The email FormControl has a new error, so, by this way i can attach a error message for this error.