1

I wan to set the validation error based on data present in the database.

Formcontrol with custom validator function:

nUname: ['', [Validators.required,unique_uname]]

Custom validator function:

Below function takes the username and using post request in service fetch the data. If the username is in database service return response with status as 'S' else error with status 'F'.

If the status is 'S' then the error 'uname_repeat' should be set to the formcontrol. uname_repeat error is not setting in subscribe, but outside subscribe it working as required.

function unique_uname(){
  return (control: AbstractControl): {[key: string]:any} | null => {
    const uname = control.value;
    if(uname.length!=0){
      ser.get_user(uname).subscribe(
        (res) => {
          if (res['status']=='S') {
             return {'uname_repeat':true} <-- This is not working
          }
        },
        (err) => {
          if (err['error']['status']=='F') {
            return null;
          }
        }

        );
        return {'uname_repeat':true} <-- This working

      }
      return null;
    };
  }

What modification are required to get the expected result.

Striker
  • 61
  • 1
  • 9

1 Answers1

0

What you need to use here is async validator.

There are 2 ways to use async validators in reactive form.

First, You can add the validation function in the component and include it in your reactive form.

validateEmailNotTaken(control: AbstractControl) {
    return this.signupService.checkEmailNotTaken(control.value).pipe(
        map(res => {
            return res ? null : { emailTaken: true };
        })
    );
}

and include in form like:

this.myForm = this.fb.group({
    name: ['', Validators.required],
    email: [
        '',
        [Validators.required, Validators.email],
        this.validateEmailNotTaken.bind(this)
    ]
});

OR Second, you can create a separate validation file

export class ValidateEmailNotTaken {
    static createValidator(signupService: SignupService) {
        return (control: AbstractControl) => {
            return signupService.checkEmailNotTaken(control.value).pipe(
                map(res => {
                    return res ? null : { emailTaken: true };
                })
            );
        };
    }
}

and include in form like:

this.myForm = this.fb.group({
    name: ['', Validators.required],
    email: [
        '',
        [Validators.required, Validators.email],
        ValidateEmailNotTaken.createValidator(this.signupService)
    ]
});

Here is a stackblitz demo for referance.

Iftifar Taz
  • 799
  • 6
  • 13