3
votes

I have an issue with my usage of angular 2 async validators.

I have the following component:

@Component({
  templateUrl: './send-activation-information.component.html'
})
export class SendActivationInformationComponent implements OnInit {

  activationInformationForm: FormGroup;
  submitted: boolean = false;  

  constructor(private userAccountService: UserAccountService,
              private formBuilder: FormBuilder,
              private router: Router) {
  }

  ngOnInit() {
    this.activationInformationForm = this.formBuilder.group({
      email: ['', [
        Validators.required,
        Validators.pattern(AppConstants.EMAIL_PATTERN)
      ], [
        validateEmailKnownFactory(this.userAccountService),
        validateUserAccountNonActivatedFactory(this.userAccountService)
      ]]
    });
  }

  sendActivationInformation() {
    this.submitted = true;
    if (this.activationInformationForm.valid) {     
        this.userAccountService.sendActivationInformation(this.activationInformationForm.value)
        .subscribe(() => this.router.navigate(['/sendactivationinformation/success']));
    }
  }
}

which uses two sync validators and two async validators specified in two arrays.

For some reason the following async validator always indicates a validation error:

export function validateUserAccountNonActivatedFactory(userAccountService: UserAccountService): {[key: string]: any} {
  return (control: AbstractControl) => {
    return userAccountService.userAccountAlreadyActivated(control.value)
      .map(alreadyActivated => alreadyActivated ? {userAccountNonActivatedValidator: {alreadyActivated: true}} : null);
  };
}

...whether or not the backend call returns false or true.

FYI, userAccountAlreadyActivated does a http call to the backend as follows:

  userAccountAlreadyActivated(email: string) {
    let body = 'email=' + email;
    return this.http.get(this.urls.USER_ACCOUNT.ALREADY_ACTIVATED + body);
  }
1
I am suspecting the issue is related to the way I specify the async validator array but I am not sure. - balteo
Does it work if you only add the async validators or even only one async validator? - Günter Zöchbauer
No. You're right the validator does not work on its own (I have commented the first validator). And it is in error whether or not true or false is returned from the backend... - balteo
Have you tried to call the validator directly like var f = validateUserAccountNonActivatedFactory(this.userAccountService); f(someControl).subscribe(val => console.log(val)); just for debugging purposes? - Günter Zöchbauer
Can you guarantee that this is a async-related thing? I have the same problem with non-async arrays: stackoverflow.com/questions/41769431/… Also, what angular version are you using? I'm on 2.4.4. - sandrooco

1 Answers

0
votes

I had forgotten to map the result to json...

Thus, changing from:

  userAccountAlreadyActivated(email: string) {
    let body = 'email=' + email;
    return this.http.get(this.urls.USER_ACCOUNT.ALREADY_ACTIVATED + body);
  }

to:

  userAccountAlreadyActivated(email: string) {
    let body = 'email=' + email;
    return this.http.get(this.urls.USER_ACCOUNT.ALREADY_ACTIVATED + body).map(res => res.json());
  }

fixed the issue - which had nothing to do with angular validators per say.