Angular 8 - Валидатор с вызовом AngularFireDatabase - PullRequest
0 голосов
/ 30 апреля 2020

У меня проблема при создании валидатора, который вызывает базу данных firebase. Код ниже, давайте посмотрим на валидатор. Предположим, у меня есть массив ['track1','track2'] в базе данных. Когда поле trackName заполнено значением track1, консоль возвращает a, как и должно быть. Но я понял, что ошибка existingTrack не появилась. Вместо этой ошибки я получил ниже упомянутые ошибки в FormGroup:

errors:
closed: false
destination: SafeSubscriber {closed: false, _parent: null, _parents: null, _subscriptions: null, syncErrorValue: null, …}
isStopped: false
syncErrorThrowable: true
syncErrorThrown: false
syncErrorValue: null
_parent: null
_parents: null
_subscriptions: [MapSubscriber]
__proto__: Object

Я попытался изменить validator на asyncValidator в конструкторе форм, но после этого валидатор перестал работать вообще , Я думаю, что может быть что-то не так со словами подписки и канала, я не уверен, когда использовать какое.

Код компонента:

constructor(public fb: FormBuilder, private dataService: DataService) {}

ngOnInit() {

this.form = this.fb.group({
          newTrack: this.fb.control(false, Validators.required),

          trackName: this.fb.control(''),
          trackLength: this.fb.control('', [Validators.pattern('^[0-9]{1,}.[0-9]{1,2}$')]),
          trackSelect: this.fb.control(''),

          time: this.fb.control('', [Validators.required, Validators.pattern('^[0-9]{1,}:[0-9]{2}$')]),
          date: this.fb.control('', [Validators.required])
      }, 
      {validator: this.tracksDataValidator.bind(this)});
}

    tracksDataValidator(group: FormGroup) {

            const newTrack = group.get('newTrack').value;
            const trackSelect = group.get('trackSelect').value;
            const trackName = group.get('trackName').value;
            const trackLength = group.get('trackLength').value;


            return this.dataService.isTrackTaken(trackName).subscribe((res: any[]) => {
                    if (newTrack === true) {
                        if (res.length > 0) {
                            console.log('a');
                            return {existingTrack: true};
                        }
                        if (trackName === '' || trackLength === '') {
                            return {newTrackNotFilled: true};
                        }
                    } else {
                        if (trackSelect === '') {
                            return {noTrackSelected: true};
                        } else {
                            return null;
                        }
                    }
                });
        }

DataService

constructor(private db: AngularFireDatabase) {}

isTrackTaken(trackName: string) {
        return this.db.list('/tracks').valueChanges()
            .pipe(map(tracks => tracks.filter((track: Track) => track.name === trackName)));
    }

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

Я пытался создать валидатор точно так же, как на сайте alligator.io, я изменил конструктор форм на

this.form = this.fb.group({
          newTrack: this.fb.control(false, Validators.required),

          trackName: this.fb.control('', [Validators.required], this.trackDataValidator.bind(this)),
          trackLength: this.fb.control('', [Validators.pattern('^[0-9]{1,}.[0-9]{1,2}$')]),
          trackSelect: this.fb.control(''),

          time: this.fb.control('', [Validators.required, Validators.pattern('^[0-9]{1,}:[0-9]{2}$')]),
          date: this.fb.control('', [Validators.required])
      });

и валидатор

trackDataValidator(control: FormControl) {
      return this.dataService.isTrackTaken(control.value).subscribe((res: any[]) => {
          return (res.length > 0) ? {existingTrack: true} : null;
      });
  }

Код DataService был таким же. После каждой напечатанной буквы в поле trackName появлялась эта ошибка:

ERROR Error: Expected validator to return Promise or Observable.
    at toObservable (forms.js:1466)
    at Array.map (<anonymous>)
    at FormControl.asyncValidator (forms.js:1446)
    at FormControl._runAsyncValidator (forms.js:4100)
    at FormControl.updateValueAndValidity (forms.js:4053)
    at FormControl.setValue (forms.js:4692)
    at updateControl (forms.js:3299)
    at DefaultValueAccessor.onChange (forms.js:3271)
    at DefaultValueAccessor._handleInput (forms.js:419)
    at Object.eval [as handleEvent] (NewTrainingComponent.html:14)

1 Ответ

0 голосов
/ 30 апреля 2020

Я бы порекомендовал следующее чтение: https://alligator.io/angular/async-validators/

В основном вам нужно возвращать Наблюдаемое, а не результат подписки на Наблюдаемое.

Позвольте Я знаю, если это работает.

Кроме того, formcontrol собирается предварительно выполнить саму подписку, как только значение формы изменится так:

  • помните о вызове API и при необходимости используйте опция: {updateOn: 'blur'} (FormControl ('', {updateOn: 'blur'});)
  • Наблюдаемая необходимость завершить sh при подписке, поэтому используйте каналы: первый, последний , возьми или возьми до.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...