Я делаю веб-приложение в Angular 8 и Firebase Firestore. У меня есть форма с одним входом для ввода идентификационного номера (в виде строки). Я хочу проверить, есть ли пользователь с таким идентификатором.
Я попытался реализовать asyn c валидатор. Он проверяет, существует ли идентификатор, если нет, возвращает ошибку для отображения сообщения в шаблоне.
constructor(
private clientService: ClientService,
private fb: FormBuilder,
) {
this.clientForm = fb.group({
identificationNumber: ['', [
Validators.required,
Validators.minLength(11)
], CustomValidator.validateUser(this.clientService)]
});
}
Валидатор asyn c:
static validateUser(clientService: ClientService): AsyncValidatorFn {
return (control: AbstractControl):
Promise<ValidationErrors | null> |
Observable<ValidationErrors | null> => {
if (control.value.length !== 11) {
return of(null);
} else {
return control.valueChanges.pipe(
debounceTime(1000),
switchMap(_ =>
clientService.getClientByIdentificationNumber(control.value)
.pipe(
map(client => return client ? null : {notfound: true}),
catchError(err => return of(null))
)
),
first(),
);
}
};
}
Метод из службы, чтобы получить пользователя:
getClientByIdentificationNumber(identificationNumber: string): Observable<Client> {
return this.afs
.collection(
'clients',
ref => ref.where('identificationNumber', '==', identificationNumber)
.limit(1) // Just get one
)
.snapshotChanges().pipe(
// flatMap() will return a single Client
flatMap(actions => actions.map(a => {
const data = a.payload.doc.data() as Client;
const id = a.payload.doc.id;
console.log('getClientByIdentificationNumber'); // Called several times
return {id, ...data};
}))
);
}
Метод getClientByIdentificationNumber
из службы вызывается снова и снова, он никогда не заканчивается.
Моя цель - проверить, есть ли клиент с таким идентификатором и возвращает ошибку, правильно обрабатывая Observables для предотвращения утечек и оставляя открытые подписки по ошибке.