详解Angular Reactive Form 表单验证(2)

<div [ngClass]="{'has-error': (age.touched || age.dirty) && !age.valid }"> <label for="ageId">年龄</label> <div> <input type="number" placeholder="请输入年龄" formControlName="age"/> <span *ngIf="(age.touched || age.dirty) && age.errors"> <span *ngIf="age.errors.range"> 输入年龄不合法 </span> </span> </div> </div>

自定义验证器模板

function myCustomValidator(c: AbstractControl): {[key: string]: boolean} | null { if(somethingIsWrong) { return { 'myvalidator': true}; } return null; }

新增 ageValidator 验证器

function ageValidator(c: AbstractControl): { [key: string]: any } | null { let age = c.value; if (age && (isNaN(age) || age < 20 || age > 120)) { return { 'range': true, min: 20, max: 120 }; } return null; }

使用 ageValidator 验证器

ngOnInit(): void { this.signupForm = this.fb.group({ // ... age: ['', ageValidator] }); }

我们的 ageValidator 自定义验证器,虽然已经实现了。细心的读者应该会发现,在 ageValidator 验证器内部,我们写死了年龄的边界值 (最小值与最大值)。理想的情况下,应该能够让用户自行设定边界值。因此接下来,我们来优化一下 ageValidator 验证器。

自定义验证器 (支持参数)

自定义验证器模板 (支持参数)

function myCustomValidator(param: any): ValidatorFn { return (c: AbstractControl): {[key: string]: boolean} | null { if(somethingIsWrong) { return { 'myvalidator': true}; } return null; } }

新增 ageRange 验证器工厂

function ageRange(min: number, max: number): ValidatorFn { return (c: AbstractControl): { [key: string]: any } | null => { let age = c.value; if (age && (isNaN(age) || age < min || age > max)) { return { 'range': true, min: min, max: max }; } return null; } }

使用 ageRange 验证器工厂

ngOnInit(): void { this.signupForm = this.fb.group({ // ... age: ['', ageRange(20, 120)] }); }

介绍完如何自定义验证器,接下来我们来介绍如何实现 "跨字段验证" 的功能。

跨字段验证

在日常生活中,在注册表单中,经常要让用户再次输入同样的字段值,比如登录密码或邮箱地址的值。针对这种场景,我们就需要验证两个控件的输入值是否一致,这时我们就要引入跨字段验证的功能。

为了演示 "跨字段验证" 的功能,我新增了一个控件:

email - 用于让用户确认输入的邮箱地址

新增 email 控件

<label for="emailId">确认邮箱</label> <div> <input type="email" placeholder="请再次输入邮箱地址" formControlName="confirmEmail"/> <span *ngIf="(confirmEmail.touched || confirmEmail.dirty)"> <span *ngIf="confirmEmail.errors?.required"> 请输入邮箱地址 </span> <span *ngIf="!confirmEmail.errors?.required && emailGroup.errors?.match"> 两次输入的邮箱地址不一致 </span> </span> </div>

新增 emailMatcher

function emailMatcher(c: AbstractControl) { let emailControl = c.get('email'); let confirmControl = c.get('confirmEmail'); if (emailControl.pristine || confirmControl.pristine) { return null; } return emailControl.value === confirmControl.value ? null : { 'match': true }; }

新增 emailGroup

ngOnInit(): void { this.signupForm = this.fb.group({ userName: ['', [Validators.required, Validators.minLength(6)]], emailGroup: this.fb.group({ email: ['', [Validators.required, Validators.email]], confirmEmail: ['', [Validators.required]], }, { validator: emailMatcher }), // ... });

更新模板

<div formGroupName="emailGroup" [ngClass]="{'has-error': emailGroup.errors }"> <label for="emailId">邮箱</label> <div> <input type="email" placeholder="请输入邮箱地址" formControlName="email"/> <span *ngIf="(email.touched || email.dirty) && email.errors"> <span *ngIf="email.errors.required"> 请输入邮箱地址 </span> <span *ngIf="!email.errors.required && email.errors.email"> 请输入有效的邮箱地址 </span> </span> </div> <!--其余部分:请参考"新增email控件"的内容--> </div>

上面代码中,有以下几个问题需要注意:

Form Group 是可以嵌套使用的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyfzwz.html