响应式表单之验证表单
添加验证器
Angular 的内置验证器由 Validators 模块提供,如果想要为 FormControl 对象添加验证器,直接将验证器作为 FormControl 的第二个参数即可。
下面例子中列举了比较常用的内置验证器及其使用形式:
例子:
form.component.html
<form [formGroup]="myGroup">
<ul>
<li>
姓名:<input type="text" formControlName="name">
</li>
<li>
性别:<input type="text" formControlName="sex">
</li>
<li>
年龄:<input type="number" formControlName="age">
</li>
<li>
血型:<input type="text" formControlName="type">
</li>
</ul>
</form>
form.component.ts
import { Component, OnInit } from '@angular/core';
// 导入校验接口 Validators
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
myGroup!: FormGroup;
constructor(
private fb: FormBuilder,
) { }
ngOnInit() {
this.myGroup = this.fb.group({
// 添加必填校验:required
name:['', Validators.required],
// 添加单个校验规则的其他方法:
// new FormControl('', Validators.required);
// this.fb.control('', Validators.required);
// 添加字符长度校验:minLength()、maxLength()
sex:['', [Validators.required, Validators.maxLength(1)]],
// 添加多个校验规则的其他方法:
// new FormControl('', [Validators.required, Validators.maxLength(1)]);
// this.fb.control('', [Validators.required, Validators.maxLength(1)]);
// 添加数值大小校验:min()、max()
age: ['', [Validators.required, Validators.min(6)]],
// 添加正则表达式:pattern()
type:['', [Validators.pattern('[a-zA-Z ]*'), Validators.maxLength(2)]]
});
}
}
自定义验证器
我们也可以创建自己的验证器。
项目结构:
例子:
form-validators.service.ts
import { Injectable } from '@angular/core';
import { ValidatorFn, FormControl, AbstractControl } from '@angular/forms';
@Injectable()
export class FormValidatorsService {
constructor() { }
// c: FormControl 或者 c: AbstractControl 都指向需要验证的内容
// AbstractControl 是 FormControl 的基类,因此它们共享 value 属性,使用哪个都可以
// 如果验证失败,返回 {[key: string]: boolean} 对象,key 为错误代码,自定义即可,boolean 为 true
// 如果验证成功,返回 null
phoneNumberValidator(c: FormControl): {[key: string]: boolean} | null {
// 验证手机号是否以数字'1'开头
if (!c.value.match(/^1/)) {
return { 'phoneNumber': true };
}
return null;
}
// 验证器函数传参的写法
areaNumberValidator(param: string): ValidatorFn {
return (c: AbstractControl): {[key: string]: boolean} | null => {
// 验证座机区号是否为 param
if(!c.value.startsWith(param)) {
return { 'areaNumber': true};
}
return null;
}
}
}
form.component.html
<form [formGroup]="myGroup">
<p>
手机:<input type="tel" formControlName="phoneNumber">
</p>
<p>
座机:<input type="tel" formControlName="areaNumber">
</p>
</form>
form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
// 导入自定义验证器 FormValidatorsService
import { FormValidatorsService } from './service/form-validators.service'
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss'],
// 将 FormValidatorsService 注入组件
providers: [
FormValidatorsService
],
})
export class FormComponent implements OnInit {
myGroup!: FormGroup;
constructor(
private fb: FormBuilder,
// 初始化 FormValidatorsService
private formValidators: FormValidatorsService
) { }
ngOnInit() {
this.myGroup = this.fb.group({
// 添加 phoneNumberValidator 验证器
phoneNumber:['', [Validators.required, this.formValidators.phoneNumberValidator]],
// 添加 areaNumberValidator 验证器,该验证器可以传参
areaNumber:['', [Validators.required, this.formValidators.areaNumberValidator('0411')]],
});
}
}
检查验证器的有效性
FormControl 与 FormGroup 的关系
FormControl 与 FormGroup 都继承自基类
AbstractControl
,因此,FormControl 与
FormGroup 共享着AbstractControl
的属性和方法,比如 value、valid、valueChanges() 等等。
FormControl 封装了单个输入字段的值和状态,比如字段是否有效,是否被修改过或者是否有错误等等。
而 FormGroup 的意义在于管理多个 FormControl,为一组 FormControl 提供总的接口,比如我们要验证多个 FormControl 是否有效(valid 属性),就需要遍历每一个 FormControl,比较繁琐,这种情况下,使用 FormGroup 就可以轻松地解决问题。
检查整个表单的有效性
结合我上面的介绍,我们通过 FormGroup 的属性 valid 就可以检查整个表单的有效性,只有当所有的 FormControl 都有效时,这个 FormGroup 才会有效。
例子:
form.component.html
<form [formGroup]="myGroup">
<p>
手机:<input type="tel" formControlName="phoneNumber">
</p>
<p>
座机:<input type="tel" formControlName="areaNumber">
</p>
<p style="color: red;">{{ errMsg }}</p>
<button (click)="save()">提交</button>
</form>
form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
myGroup!: FormGroup;
errMsg!: string;
constructor(
private fb: FormBuilder
) {}
ngOnInit() {
this.myGroup = this.fb.group({
phoneNumber:['', Validators.required],
areaNumber:['', Validators.required],
});
}
// 验证整个表单的有效性并显示错误信息
save() :boolean{
if(!this.myGroup.valid){
this.errMsg = '验证未通过!';
return false;
}
console.log(this.myGroup.value);
this.errMsg = '';
return true;
}
}
检查单个字段的有效性
很多时候,我们需要知道哪个字段无效,导致了验证的失败,所以,检查单个字段的有效性并显示错误消息是更加实际的需求。
为单个 FormControl 进行验证,我们必须为每个字段定义一个变量,并为变量添加 getter 方法。
例子:
form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
myGroup!: FormGroup;
errMsg!: string;
// 声明变量 phoneNumber、areaNumber
// 这样,在组件和模板中,就可以到处引用变量
get phoneNumber(){
// 使用 FormGroup 的 get 方法或 controls 获取单个字段
return this.myGroup.get('phoneNumber');
// return this.myGroup.controls['phoneNumber'];
}
get areaNumber(){
return this.myGroup.get('areaNumber');
// return this.myGroup.controls['areaNumber'];
}
constructor(
private fb: FormBuilder
) {}
ngOnInit() {
this.myGroup = this.fb.group({
phoneNumber:['', Validators.required],
areaNumber:['', Validators.required],
});
}
save() :boolean{
if(!this.myGroup.valid){
console.log('保存失败');
return false;
}
console.log(this.myGroup.value);
return true;
}
}
form.component.html
<form [formGroup]="myGroup">
<p>
手机:<input type="tel" formControlName="phoneNumber">
<!-- 在模板中引用变量 -->
<!-- phoneNumber.valid:验证 phoneNumber 是否有效 -->
<!-- phoneNumber.touched:验证 phoneNumber 是否被修改 -->
<i style="color: red;" *ngIf="!phoneNumber?.valid && phoneNumber?.touched">手机验证未通过!</i>
</p>
<p>
座机:<input type="tel" formControlName="areaNumber">
<i style="color: red;" *ngIf="!areaNumber?.valid && areaNumber?.touched">座机验证未通过!</i>
</p>
<button (click)="save()">提交</button>
</form>
特定验证
一个字段可能添加了很多验证器,对于失败的原因,我们更希望根据不同的原因提示不同的消息。
我们可以使用 hasError() 检查哪些验证失败。
例子:
form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
myGroup!: FormGroup;
errMsg!: string;
get phoneNumber(){
return this.myGroup.get('phoneNumber');
}
constructor(
private fb: FormBuilder
) {}
ngOnInit() {
this.myGroup = this.fb.group({
phoneNumber:['', [Validators.required, Validators.pattern('^[0-9]*$')]
]
});
}
save() :boolean{
if(!this.myGroup.valid){
console.log('保存失败');
return false;
}
console.log(this.myGroup.value);
return true;
}
}
form.component.html
<form [formGroup]="myGroup">
<p>
手机:<input type="tel" formControlName="phoneNumber">
<span style="color: red;" *ngIf="!phoneNumber?.valid && phoneNumber?.touched">
<i *ngIf="phoneNumber?.hasError('required')">必填!</i>
<i *ngIf="phoneNumber?.hasError('pattern')">必须是数字!</i>
</span>
</p>
<button (click)="save()">提交</button>
</form>
end
共同学习,写下你的评论
评论加载中...
作者其他优质文章