无法读取null的属性'...' - Angular 2

时间:2018-03-23 10:33:31

标签: angular

我正在尝试创建一个自定义异步验证程序,用于检查提供的电子邮件是否已存在于数据库中。当出现错误时,它可以正常工作,但是当错误解决后(输入有效数据),它会显示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验证器

时,也会出现同样的错误

ScreenShot

2 个答案:

答案 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>