我正在尝试创建一个自定义异步验证程序,用于检查提供的电子邮件是否已存在于数据库中。当出现错误时,它可以正常工作,但是当错误解决后(输入有效数据),它会显示Cannot read property 'emailIsTaken' of null
我正在使用模板驱动方法。这是我的使用方式。
<input type="email" name="email" [(ngModel)]='email' #mail='ngModel' required [pattern]='emailPattern' validateEmail>
使用错误代码
<div *ngIf='mail.errors["emailIsTaken"]'>Email already Registered!</div>
这是我的验证器文件
import { Validator, AbstractControl, NG_ASYNC_VALIDATORS } from '@angular/forms';
import { Directive, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Directive({
selector: '[validateEmail]',
providers: [{
provide: NG_ASYNC_VALIDATORS,
useExisting: EmailValidator,
multi: true
}]
})
@Injectable()
export class EmailValidator implements Validator {
constructor(private http: HttpClient){}
validate(control: AbstractControl): Promise<any> | Observable<any> {
return new Promise(resolve => {
this.http.get('http://surjit.com/email.php?q=' + control.value).subscribe((success)=>{
if(success === true){
resolve(null);
}
else{
resolve({'emailIsTaken': true});
}
});
});
}
}
当我使用内置email
验证器
答案 0 :(得分:1)
这是你的问题:
if(success === true){
resolve(null);
}
如果验证成功,则返回null,而不是带有'emailIsTaken'字段的对象。
怎么样?
if(success === true){
resolve({'emailIsTaken': false});
}
如果这符合您的代码?
答案 1 :(得分:0)
如果要执行此异步,则需要实现AsyncValidator
。
此外,您需要从observable返回结果而不是订阅它。这里最简单的方法是使用Observable而不是promise,但您也可以在.toPromise()
之后链接.map()
。你不想在这里订阅你想要返回observable本身(或者promise),但你确实希望让promise返回预期的结果,这就是你应该使用map
的原因。
另外,如果您还没有这样做,我建议您切换到使用pipable操作符。另请参阅In Angular rxjs when should I use pipe
vs map
。
import { AsyncValidator } from '@angular/forms';
import { map } from 'rxjs/operators/map';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class EmailValidator implements AsyncValidator {
constructor(private http: HttpClient){}
validate(control: AbstractControl): Promise<any> | Observable<any> {
return this.http.get('http://surjit.com/email.php?q=' + control.value)
.pipe(map((success)=> success ? null : {'emailIsTaken': true}));
}
}
以上只是更改过的EmailValidator
类。
请参阅我根据上述内容创建的StackBlitz。
根据您的错误屏幕截图,最可能的原因是您在HTML中检查了哪些错误应根据生成的验证显示,并且未考虑验证结果为null
的事实如果没有错误。最简单的解决方法是使用safe navigation operator ( ?. ) and null property paths ?
。例如:
<element *ngIf="errResult?.emailIsTaken">Email is in use</element>