I am trying to create custom validator which needs to hit two endpoint to fetch needed data and then compare properties of the data and if they are not equal then I want to throw an error. Here is the validator.
checkIfSalaIsFull(control: AbstractControl): {[salaIsFull: string] : boolean}{
if(control.value !=null){
this.salaService.findActiveCards(control.value).subscribe(karty=>{
this.salaService.findSalaByNRSali(control.value).subscribe(sala =>{
if(karty.length === sala.pojemnosc){
console.log(karty.length);
console.log(sala.pojemnosc);
return {'salaIsFull' : true};
}
});
});
}
return null;
}
The problem is that error is not thrown even though console.log show the same value for showed properties.
<div class="form-group">
<label for="nr_sali">Numer sali</label>
<select class="form-control" id="nr_sali" formControlName="nr_sali">
<option *ngFor="let sala of sale" [value]="sala.nr_sali" >{{sala.nr_sali}} - {{sala.oddzial}}</option>
</select>
<span *ngIf="formAddKarta.get('nr_sali').errors?.salaIsFull"
class="help-block text-danger">
Sala jest pełna
</span>
</div>
My backend is working, I checked it with postman.
Here is also a setup of FormGroup which I am using:
this.formAddKarta = new FormGroup({
data_przyjecia: new FormControl(null, [KartyListaComponent.checkIfDateIsLessThanToday.bind(this),
Validators.required]),
godzina_przyjecia: new FormControl(null,[Validators.required]),
data_wypisu: new FormControl(null),
nr_sali: new FormControl(null, [Validators.required,this.checkIfSalaIsFull.bind(this)]),
pesel: new FormControl(this.pesel)
});
I set this custom validator in Validators table in nr_sali FormControl.
EDIT:
I tried to use map instead of subscribe but then it is not sending request to retrieve sala, only sending request to retreive karty.
checkIfSalaIsFull(control: AbstractControl): {[salaIsFull: string] : boolean}{
if(control.value !=null){
this.salaService.findActiveCards(control.value).subscribe(karty=>{
this.salaService.findSalaByNRSali(control.value).pipe(map(sala =>{
if(karty.length === sala.pojemnosc){
console.log(karty.length);
console.log(sala.pojemnosc);
return {'salaIsFull' : true};
}else{
return null;
}
}));
});
}else{
return null;
}
}
Observable<ValidationErrors | null> | Promise<ValidationErrors | null>
switchMap and map
instead of subscription here is the code example
imports
import { map, switchMap } from "rxjs/operators";
import { Observable } from "rxjs/internal/observable";
async validator example
checkIfSalaIsFull(
control: AbstractControl
): Observable<ValidationErrors | null> {
if (control.value != null) {
return this.salaService.findActiveCards(control.value).pipe(
switchMap(karty => {
return this.salaService.findSalaByNRSali(control.value).pipe(
map(sala => {
console.log(karty.length);
console.log(sala.pojemnosc);
return karty.length === sala.pojemnosc ? { salaIsFull: true } : null;
})
);
})
);
}
return null;
}
Form Implementation example
this.formAddKarta = new FormGroup({
data_przyjecia: new FormControl(null, [
KartyListaComponent.checkIfDateIsLessThanToday.bind(this), /** <-- if this function send the request you need to change this one too */
Validators.required]),
godzina_przyjecia: new FormControl(null, [Validators.required] ),
data_wypisu: new FormControl(null),
nr_sali: new FormControl(null,
[Validators.required],
[this.checkIfSalaIsFull.bind(this)]), /** <-- third argument of formControl is the async validators array */
pesel: new FormControl(this.pesel)
});