Reputation: 75
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;
}
}
Upvotes: 0
Views: 240
Reputation: 4453
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)
});
Upvotes: 2
Reputation: 1136
Continuing from my above comments, you want to use map instead of subscribe. Since Angular 6, rxjs (the library map comes from) wraps requires it's operations to be wrapped in a pipe function like so:
import { map } from 'rxjs/operations'
...
this.salaService.findSalaByNRSali(control.value).pipe(map(sala => {
// Do work
// ...
}));
Upvotes: 0