У меня проблема при создании валидатора, который вызывает базу данных 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)