RRGT19
RRGT19

Reputation: 1677

Add async validator to FormControl dynamically

I'm doing a web application in Angular 8. I have a form with just 1 input to enter a 5 digits number (as string). I want to validate that this number is unique in the database.

I have tried to implement an async validator. I need to pass to it a few variables, so, I have added the validators later dynamically.

brand: Brand;
raffle: Raffle;

constructor(
    private brandService: BrandService,
    private fb: FormBuilder,
  ) {
    this.gambleForm = fb.group({
      number: ['', [ // Default validators
        Validators.required,
        Validators.minLength(5),
        Validators.maxLength(5),
      ]]
    });
  }

ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id');
    this.getBrandData(id);
  }

getBrandData(id: string) {
    this.brandService.getBrandById(id).subscribe(res => {
      this.brand = res;
      this.getRaffleData();
    });
  }

getRaffleData() {
    this.brandService.getLastRaffleOpen(this.brand.id)
      .subscribe(res => {
        this.raffle = res;
        // Adding validators dynamically
        this.gambleForm.get('number').setValidators([
          // Returns a compose validator containing all previously defined validators.
          this.gambleForm.get('number').validator,
          // Async validator
          CustomValidator.numberCanBePlayed(
            this.brandService.getFirestore(),
            this.brand.id,
            this.raffle.id
          )
        ]);
      });
  }

Right now, my async validator is not working because, according to what I have read, I'm assigning it as sync validator, instead of async. How can I assign the async validator correctly? I'm assign it later because I need to pass a few variables to the async validator, which are not available inside of the construction of the form.

My goal is to assign my async validator dynamically.

Upvotes: 0

Views: 3383

Answers (2)

Fateh Mohamed
Fateh Mohamed

Reputation: 21377

You can try this when you have an error from the backend and use setErrors on the the correspondent formControl , here is an example to check if the email is taken or not

subscribe((data) => {// do control here},
   error => { 
    if(error.status === 400 && error.error.errors.email) {
      const emailFormControl = this.accountForm.get('email');
      if (emailFormControl) {
      // activate the error message
      emailFormControl.setErrors({
        serverError: 'Email exist déjà!'
      });
     }
    }
});

and you can show the error in the template like this

<mat-error *ngIf="accountForm.get('email').errors?.serverError">
              {{ accountForm.get('email').errors?.serverError }}
</mat-error>

Upvotes: 0

mbojko
mbojko

Reputation: 14679

FormControl has a special method for that: setAsyncValidators: https://angular.io/api/forms/AbstractControl#setAsyncValidators

Upvotes: 1

Related Questions