Angular 自定义验证器在其中使用订阅时不会抛出错误

Angular custom validator is not throwing an error when using subscribe in it

我正在尝试创建自定义验证器,它需要命中两个端点以获取所需的数据,然后比较数据的属性,如果它们不相等,那么我想抛出一个错误。这是验证器。

 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;
  }

问题是即使 console.log 显示的属性值相同,也不会抛出错误。

<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>

我的后端工作正常,我和邮递员核实过。

这也是我正在使用的 FormGroup 的设置:

 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)
    });

我在 nr_sali FormControl 的验证器 table 中设置了这个自定义验证器。

编辑:

我尝试使用 map 而不是 subscribe,但它没有发送检索 sala 的请求,只发送检索 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;
    }

  }

继续我上面的评论,您想使用地图而不是订阅。自 Angular 6 起,rxjs(库映射来自)包装要求将其操作包装在管道函数中,如下所示:

import { map } from 'rxjs/operations'

...

this.salaService.findSalaByNRSali(control.value).pipe(map(sala => { 
  // Do work
  // ...
}));
  1. 你需要使用异步验证器而不是验证器,因为你需要发送请求,并且你需要将你的函数作为第三个参数放在你的 formControl 中(作为异步验证器)
  2. 你的验证器函数应该是 return Observable<ValidationErrors | null> | Promise<ValidationErrors | null>
  3. 您需要使用 switchMap and map 而不是订阅

这里是代码示例

进口

import { map, switchMap } from "rxjs/operators";
import { Observable } from "rxjs/internal/observable";

异步验证器示例

  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;
  }

表单实现示例

 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)
    });