Angular Form表单自定义验证器(同步)
2018-12-03 本文已影响65人
前端转转
在web应用里,我们都知道表单基本无处不在,如登录、注册、个人信息收集等。为了在应用里提高用户体验,在处理表单时,我们往往要引入表单验证。在Angular里有一些内置验证器,但是在实际应用当中,内置验证器往往不够我们用。
表单验证
通过验证用户输入的准确性和完整性,来增强整体数据质量。
对angular Form学习后我们知道表单分为两种:
- 模板驱动型表单:它们很容易添加到应用中,但是不像响应式表单那么容易扩展。
- 响应式驱动(模型驱动)表单:提供了一种模型驱动的方式来处理表单输入,其中的值会随时间而变化.响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态.
在自定义验证器时需要分别去对应这两种类型的表单。在本文里,我们不讨论这两种表单的数据流,只讨论自定义验证器的实现。对于内置验证器,可以去官方文档里查看,每一验证器都有例子。
模板驱动型表单自定义验证器(同步)
我们用一个简单的例子来帮助我们实现一个模板驱动型表单的自定义同步验证器。这个例子是:禁止输入Patrick。
- 第一步创建指令。
- 导入Input,NG_VALIDATORS, Validators, AbstractControl。
import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validators, AbstractControl } from "@angular/forms"
@Directive({
selector: '[appMyValidationTwo]',
providers:[{provide: NG_VALIDATORS, useExisting: MyValidationTwoDirective, multi: true}]
})
export class MyValidationTwoDirective implements Validators{
constructor() { }
@Input('appMyValidationTwo') forbiddenName:string;
validate(contrl: AbstractControl): {[key:string]:any} | null{
return this.forbiddenName ? (this.forbiddenName === contrl.value?{'forbiddenName':contrl.value} :null) : null;
// 这里面书写你的验证器的逻辑。
}
}
- 导入Input:因为验证器需要模板输入值
- NG_VALIDATORS:指令把自己注册到了NG_VALIDATORS提供商中,该提供商拥有一组可扩展的验证器
3.添加到模板驱动表单中
{{name.errors | json}} //把错误打印在页面中。
<input id="name" name="name" class="form-control"
required minlength="2" appMyValidationTwo = 'Patrick'
[(ngModel)]="hero.name" #name="ngModel" >
<div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required.
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 2 characters long.
</div>
<div *ngIf="name.errors.forbiddenName">
Name cannot be Patrick.
</div>
</div>
就像属性指令那样,在元素上使用即可。当在输入框输入Patrick时,该验证器会返回一个错误对象;如果输入的内容不是验证器禁止的内容时,会返回null,返回null即代表表单输入无误。试一试。
响应式驱动表单自定义验证器(同步)
以同样的例子(禁止输入Patrick)来实现响应式驱动表单的同步自定义验证器。
- 创建一个工厂函数
import {ValidatorFn, AbstractControl} from "@angular/forms"
//响应式表单自定义模板验证器
export function forbiddenNameValidator(name:string):ValidatorFn{
return (contrl:AbstractControl): {[key: string]: any} | null=>{
const forbidden = name === contrl.value;
return forbidden ? {'forbiddenName': {value: contrl.value}} : null;
}
}
- 把自定义验证器添加到响应式驱动表单
profileForm = this.fb.group({
nameTwo : ['Bob',
[Validators.required,Validators.minLength(2),forbiddenNameValidator("Patrick")]
],
id : [123,Validators.required]
});
get id(){
return this.profileForm.get('id');
}
get nameTwo(){
return this.profileForm.get('nameTwo');
}
我们用getter获取formControl并设置给nameTwo属性,这样我们就能在模板里处理验证器的错误了。
<form [formGroup] = 'profileForm'>
<div class="form-group">
<label for="nameTwo">Name</label>
<input type="text" class="form-control" id="nameTwo" formControlName="nameTwo" required>
</div>
<div *ngIf="nameTwo.errors && nameTwo.errors.required">
Name is required.
</div>
<div *ngIf="nameTwo.errors && nameTwo.errors.minlength">
姓名的最小长度为2
</div>
<div *ngIf="nameTwo.errors && nameTwo.errors.forbiddenName"> //对自定义同步验证器错误的处理
姓名不能为Patrick
</div>
<div class="form-group">
<label for="id">Id</label>
<input type="text" class="form-control" id="id" formControlName="id" required>
</div>
<div *ngIf="id.errors && id.errors.required">ID是必选项</div>
<button type="submit" class="btn btn-default" [disabled]="profileForm.invalid">Submit</button>
</form>
这就是一个实现响应式模板驱动表单的验证器的简单例子。试试吧。