Angular Пользовательский валидатор не выдает ошибку при использовании подписки в нем - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь создать пользовательский валидатор, которому нужно нажать две конечные точки, чтобы получить необходимые данные, а затем сравнить свойства данных, и если они не равны, я хочу выдать ошибку. Вот валидатор.

 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.

РЕДАКТИРОВАТЬ:

Я пытался использовать карту вместо подписки, но тогда он не отправляет запрос на получение sala, а только отправляет запрос на получение карты.

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

  }

Ответы [ 2 ]

2 голосов
/ 15 января 2020
  1. вам нужно использовать валидатор asyn c вместо валидатора, потому что вам нужно отправить запрос, и вам нужно поместить свою функцию в качестве третьего параметра в вашем formControl (как Asyn c валидатор)
  2. ваша функция валидатора должна быть возвращена Observable<ValidationErrors | null> | Promise<ValidationErrors | null>
  3. вам нужно использовать switchMap and map вместо подписки

вот пример кода

import

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

asyn c пример валидатора

  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)
    });
0 голосов
/ 15 января 2020

Продолжая мои комментарии, вы хотите использовать карту вместо подписки. Поскольку Angular 6, rx js (карта библиотеки взята) требует, чтобы его операции были упакованы в функцию конвейера следующим образом:

import { map } from 'rxjs/operations'

...

this.salaService.findSalaByNRSali(control.value).pipe(map(sala => { 
  // Do work
  // ...
}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...