См. Обновления ниже
Я понимаю, что моя проблема в том, что я очень зеленый в наблюдаемых и RxJS.
У меня есть пользовательскийвалидатор, подобный этому:
export function ValidateFinalQty(service: MyService) {
return (control: AbstractControl): { [key: string]: any } | null => {
let qty = service.GetQty();
if (control.value != qty) {
return { FinalQuantityNotMatching: true };
} else {
return null;
}
};
}
GetQty возвращает RxJS Observable.Так как я могу настроить это так, чтобы мой синхронный валидатор возвращал правильное значение в зависимости от асинхронного вызова?Мне нужно, чтобы тип возвращаемого значения валидатора оставался как { [key: string]: any } | null
.
Я увидел предложение, похожее на qty = await service.GetQty().first().toPromise();
, но затем я возвращаю обещание и не могу вернуть обещание для валидатораработать, как я понимаю.
Как мне справиться с этим?
Из моего package.json
:
"@angular/core": "7.1.0",
"@angular/forms": "7.1.0",
"rxjs": "6.3.3",
"rxjs-compat": "^6.4.0",
ОБНОВЛЕНИЕ 23.05.199 Попытка реализовать ответ @ Sachin.Мои контрольные точки внутри карты никогда не будут поражены.Я не получаю никаких журналов консоли, и даже если я удаляю логику на карте и возвращаю ноль, он все равно всегда возвращает недействительным.Очень смущен тем, что здесь происходит.На самом деле мне звонят, я это подтвердил.
Есть мысли?
export class CustomAsyncValidator {
static ValidateFinalQty(qtyService: FinalQtyService, brf: BatchRecordForm): AsyncValidatorFn {
return (control: AbstractControl) => {
return qtyService.postCalcFinalQuanity(brf)
.pipe(
map((qty) => {
console.log("running qty validator. value:", qty);
if (control.value !== qty) {
return { FinalQuantityNotMatching: true };
} else {
return null;
}
}),
catchError((err) => {
console.log("Error in final quantity validator", err);
return null;
}),
finalize(() => console.log("finished"))
);
};
}
}
ОБНОВЛЕНИЕ 6/7/2019
При подписке я получаю правильный ответ (null или {FinalQuantityNotMatching: true}), но мой элемент управления формы остается недействительным.Что я делаю не так?
Validator.ts
export class CustomAsyncValidator {
static ValidateFinalQty(fqs: FinalQtyService, brf: BatchRecordForm) {
return (control: AbstractControl) => {
return fqs.postCalcFinalQuanity(brf).pipe(
debounceTime(500),
tap((action) => console.log("final qty", action)),
tap((action) => console.log("control.value", control.value)),
map(arr => (arr.Value !== `${control.value}`) ? { FinalQuantityNotMatching: true } : null)
).subscribe(x => console.log("subscribe output", x));
};
}
}
component.ts
this.noteForm.addControl(this.finalQtyFormControlName, new FormControl(this.noteSubModuleForm.Value,
[Validators.required, CustomAsyncValidator.ValidateFinalQty(this.finalQtyService, this.embrService.batchRecordForm)]));
ОБНОВЛЕНИЕ 6/7/2019 # 2
После https://www.youtube.com/watch?v=zeX5CtFqkXQ Я смог сделать валидатор на основе директив, но все равно предпочел бы иметь валидатор в моем TS, если вы видите, что я сделал неправильно в предыдущемОбновить.
@ Directive ({селектор: "[validFinalQty]", поставщики: [{Обеспечить: NG_ASYNC_VALIDATORS, useExisting: ValidateFinalQtyDirective, multi: true}]})
export class ValidateFinalQtyDirective implements AsyncValidator {
constructor(private fqs: FinalQtyService, private embrService: EmbrService) { }
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return this.fqs.postCalcFinalQuanity(this.embrService.batchRecordForm).pipe(
tap(x => {
console.log("final qty", x);
console.log("control.value", control.value);
}),
map(arr => (arr.Value !== `${control.value}`) ? { FinalQuantityNotMatching: true } : null)
);
}