我正在构建一个Angular 4应用程序,它需要在几个组件中对表单字段进行BriteVerify电子邮件验证。我正在尝试将此验证实现为一个自定义异步验证器,可以用于React式表单。目前,我可以获得API响应,但控件状态停留在挂起状态。我没有收到错误,所以我有点困惑。请告诉我哪里做错了。以下是我的代码。
组件
import { Component,
OnInit } from '@angular/core';
import { FormBuilder,
FormGroup,
FormControl,
Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { EmailValidationService } from '../services/email-validation.service';
import { CustomValidators } from '../utilities/custom-validators/custom-validators';
@Component({
templateUrl: './email-form.component.html',
styleUrls: ['./email-form.component.sass']
})
export class EmailFormComponent implements OnInit {
public emailForm: FormGroup;
public formSubmitted: Boolean;
public emailSent: Boolean;
constructor(
private router: Router,
private builder: FormBuilder,
private service: EmailValidationService
) { }
ngOnInit() {
this.formSubmitted = false;
this.emailForm = this.builder.group({
email: [ '', [ Validators.required ], [ CustomValidators.briteVerifyValidator(this.service) ] ]
});
}
get email() {
return this.emailForm.get('email');
}
// rest of logic
}
验证器类
import { AbstractControl } from '@angular/forms';
import { EmailValidationService } from '../../services/email-validation.service';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
export class CustomValidators {
static briteVerifyValidator(service: EmailValidationService) {
return (control: AbstractControl) => {
if (!control.valueChanges) {
return Observable.of(null);
} else {
return control.valueChanges
.debounceTime(1000)
.distinctUntilChanged()
.switchMap(value => service.validateEmail(value))
.map(data => {
return data.status === 'invalid' ? { invalid: true } : null;
});
}
}
}
}
服务
import { Injectable } from '@angular/core';
import { HttpClient,
HttpParams } from '@angular/common/http';
interface EmailValidationResponse {
address: string,
account: string,
domain: string,
status: string,
connected: string,
disposable: boolean,
role_address: boolean,
error_code?: string,
error?: string,
duration: number
}
@Injectable()
export class EmailValidationService {
public emailValidationUrl = 'https://briteverifyendpoint.com';
constructor(
private http: HttpClient
) { }
validateEmail(value) {
let params = new HttpParams();
params = params.append('address', value);
return this.http.get<EmailValidationResponse>(this.emailValidationUrl, {
params: params
});
}
}
模板(仅表格)
<form class="email-form" [formGroup]="emailForm" (ngSubmit)="sendEmail()">
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<fieldset class="form-group required" [ngClass]="{ 'has-error': email.invalid && formSubmitted }">
<div>{{ email.status }}</div>
<label class="control-label" for="email">Email</label>
<input class="form-control input-lg" name="email" id="email" formControlName="email">
<ng-container *ngIf="email.invalid && formSubmitted">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Please enter valid email address.
</ng-container>
</fieldset>
<button type="submit" class="btn btn-primary btn-lg btn-block">Send</button>
</div>
</div>
</form>
5条答案
按热度按时间h9vpoimq1#
有一个**gotcha**!
也就是说,你的观察永远不会完成......
发生这种情况是因为观察对象永远不会完成,所以Angular不知道什么时候改变形态状态。所以记住你的观察对象必须完成。
您可以通过许多方式来实现这一点,例如,您可以调用
first()
方法,或者如果您正在创建自己的观察对象,则可以调用观察对象上的complete方法。所以你可以用
first()
稍微修改的验证器,即总是返回错误:* * 第一个e第一个f第一个x
稍微修改的验证器,即总是返回错误:* * 一个月一次**
bxfogqkk2#
因此,我所做的是在用户名未被采用时抛出404,并使用订阅错误路径来解析null,当我得到响应时,我使用错误进行了解析。另一种方法是通过响应对象返回一个数据属性,该属性可以是用户名的宽度填充值,也可以是空值,并使用404的内部
前。
在本例中,我绑定(this)以便能够在validator函数中使用我的服务
我的组件类ngOnInit()的摘录
从我的验证器类中提取
bmvo0sr53#
我一直在做稍微不同的事情,面临着同样的问题。
下面是我的代码和修复的情况下,如果有人会需要它:
uujelgoq4#
我尝试使用@AT82描述的
.first()
.技术,但我没有发现它解决了问题。我最终发现表单的状态正在改变,但是因为我使用的是
onPush
,所以状态改变没有触发改变检测,所以页面中没有任何东西更新。我最终采用的解决方案是:
7lrncoxx5#