当我实际进行异步调用时,我的异步验证器不起作用(但是当我用Observable.of(result)
模拟它时可以工作。html
如下所示:
<div class="form-group">
<label for="emailAddress" class="control-label">Email</label>
<input type="email"
id="emailAddress"
class="form-control"
[(ngModel)]="parent.EmailAddress"
name="emailAddress"
[ngModelOptions]="{updateOn: 'blur'}"
appDuplicateEmailValidator
#emailAddress = "ngModel">
</div>
有问题的验证器是appDuplicateEmailValidator
.
验证代码如下所示:
public validate(control: AbstractControl): Observable<ValidationErrors | null> {
// return observableOf({ 'isDuplicateEmail': true });
return this.checkForDupeUserAndGetValidationState(emailAddress);
}
private checkForDupeUserAndGetValidationState(emailAddress): Observable<ValidationErrors | null> {
const validationStateObs: Observable<ValidationErrors | null> = new Observable(observer => {
this.adminService.getUser(emailAddress).subscribe(
(res: any) => {
const validationState = !!res ? observableOf({ 'isDuplicateEmail': true }) : null;
console.log('Observer next, validation state: ', validationState); // Gets correct val state
observer.next(validationState);
console.log('Is it hitting this'); // Gets hit
}, (err) => {
observer.next(null);
});
});
一个重要的注意事项是,当我取消注释// return observableOf({ 'isDuplicateEmail': true });
时,一切都按预期工作。但是你看到上面的代码的方式,它不起作用,即使可观察量返回正确的值(将其记录为使用的调试器(。通过"它不起作用",我的意思是表单控件永远不会进入错误状态,如下所示:
<pre>IS INVALID: {{emailAddress.invalid}}</pre>
<pre>ERRORS: {{emailAddress.errors | json}}</pre>
为什么以及如何修复它?
您有 3 个问题。1. 您需要实际返回可观察量 2.您通过观察者 3 发送可观察量而不是值。需要完成可观察量。
你可以这样做:
private checkForDupeUserAndGetValidationState(emailAddress): Observable<ValidationErrors | null> {
const validationStateObs: Observable<ValidationErrors | null> = new Observable(observer => {
this.adminService.getUser(emailAddress).subscribe(
(res: any) => {
const validationState = !!res ? { 'isDuplicateEmail': true } : null; // just send the value
observer.next(validationState);
observer.complete(); //complete here
}, (err) => {
observer.next(null);
observer.complete(); // and complete here
});
});
return validationStateObs; // return it here
}
但是更容易和更干净的方法是从您的服务返回响应并使用运算符,而不是创建一个可观察的并在其中嵌套订阅。
private checkForDupeUserAndGetValidationState(emailAddress): Observable<ValidationErrors | null> {
return this.adminService.getUser(emailAddress).pipe(
map((res: any) => !!res ? { 'isDuplicateEmail': true } : null),
catchError((err) => observableOf(null))
)
}
HTTP 可观察量在一次发射后自然完成,因此您无需担心完成或任何其他复杂的逻辑。
问题是,你为什么要订阅然后作为新Observable
返回?我认为你应该能够做到这一点:
private checkForDupeUserAndGetValidationState(emailAddress): Observable<ValidationErrors | null> {
return this.adminService.getUser(emailAddress).pipe(map(
(res: any) => {
return !!res ? { 'isDuplicateEmail': true } : null;
}, catchError(err => {
return of(null);
})));
}
这样,您将让异步验证器本身为您处理订阅...
希望这有帮助...
observableOf({ 'isDuplicateEmail': true })
返回一个可观察的对吗? 你应该把 Normal 方法放在 Observer.next(( 中,而不是一个可观察的。
尝试删除可观察量并对其进行测试。 它应该是这样的:
private checkForDupeUserAndGetValidationState(emailAddress): Observable<ValidationErrors | null> {
const validationStateObs: Observable<ValidationErrors | null> = new Observable(observer => {
this.adminService.getUser(emailAddress).subscribe(
(res: any) => {
const validationState = !!res ? { 'isDuplicateEmail': true } : null;
console.log('Observer next, validation state: ', validationState); // Gets correct val state
observer.next(validationState);
console.log('Is it hitting this'); // Gets hit
}, (err) => {
observer.next(null);
});
});
我希望它以这种方式工作