Angular 4响应式表单中为非必填字段添加邮箱存在性自定义验证
Angular响应式表单:邮箱唯一性校验(REST请求实现)
先来看你编写的异步校验器代码:
emailValidator(control : FormControl) { const q = new Promise((resolve, reject) => { setTimeout(() => { this.signupService.isEmaiIDExist(control.value) .pipe(catchError(this.signupService.errorHandler)) .subscribe(res => { console.log(res) if(res.status==400) { resolve(null) }else { resolve({ 'isEmailExist': true }) } }); }, 1000); }); return q; }
代码逻辑解析
这段代码的核心思路是完全正确的:
- 用
Promise包装异步REST请求,符合Angular表单异步校验器的要求 - 调用服务层方法发送请求,检查邮箱是否已注册
- 根据接口返回状态码判断校验结果:返回400时判定邮箱可用(
resolve(null)),其他状态则标记邮箱已存在(返回{ 'isEmailExist': true }) - 加入1秒延迟可能是为了减少频繁请求,但如果不是刻意模拟加载,这个延迟可以去掉
可优化的几个细节
1. 移除不必要的延迟
如果不是为了测试加载状态,直接发起请求即可,避免让用户额外等待:
emailValidator(control: FormControl) { return new Promise((resolve, reject) => { this.signupService.isEmaiIDExist(control.value) .pipe(catchError(this.signupService.errorHandler)) .subscribe(res => { console.log(res); res.status === 400 ? resolve(null) : resolve({ 'isEmailExist': true }); }); }); }
2. 解决订阅泄漏问题
直接subscribe会存在订阅泄漏风险,建议用first()操作符自动完成订阅:
import { first } from 'rxjs/operators'; emailValidator(control: FormControl) { return new Promise((resolve, reject) => { this.signupService.isEmaiIDExist(control.value) .pipe( catchError(this.signupService.errorHandler), first() // 自动完成订阅,避免内存泄漏 ) .subscribe( res => { res.status === 400 ? resolve(null) : resolve({ 'isEmailExist': true }); }, () => { // 请求异常时可默认校验通过,或根据需求处理 resolve(null); } ); }); }
3. FormBuilder配置示例
给你补充完整的表单组配置代码,注意异步校验器要放在第三个参数数组,且需要bind(this)确保上下文正确:
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; // 组件类内 constructor(private fb: FormBuilder, private signupService: SignupService) {} signupForm: FormGroup; ngOnInit() { this.signupForm = this.fb.group({ email: [ '', [Validators.required, Validators.email], // 前端格式校验 [this.emailValidator.bind(this)] // 异步校验器,必须绑定this ] }); }
4. 模板中显示错误提示
最后在模板里添加错误提示和加载状态:
<input type="email" formControlName="email" placeholder="请输入邮箱"> <!-- 邮箱已存在提示 --> <div *ngIf="signupForm.get('email').hasError('isEmailExist')" class="error-text"> 该邮箱已被注册,请更换其他邮箱! </div> <!-- 校验加载中提示 --> <div *ngIf="signupForm.get('email').pending" class="loading-text"> 正在检查邮箱是否可用... </div>
内容的提问来源于stack exchange,提问作者Rohit Kavthekar
相关产品推荐
相关产品推荐

