詳解Angular Reactive Form 表單驗(yàn)證
本文我們將介紹 Reactive Form 表單驗(yàn)證的相關(guān)知識,具體內(nèi)容如下:
- 使用內(nèi)建的驗(yàn)證規(guī)則
- 動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則
- 自定義驗(yàn)證器
- 自定義驗(yàn)證器 (支持參數(shù))
- 跨字段驗(yàn)證
基礎(chǔ)知識
內(nèi)建驗(yàn)證規(guī)則
Angular 提供了一些內(nèi)建的 validators,我們可以在 Template-Driven 或 Reactive 表單中使用它們。
目前 Angular 支持的內(nèi)建 validators 如下:
- required - 設(shè)置表單控件值是非空的。
- email - 設(shè)置表單控件值的格式是 email。
- minlength - 設(shè)置表單控件值的最小長度。
- maxlength - 設(shè)置表單控件值的最大長度。
- pattern - 設(shè)置表單控件的值需匹配 pattern 對應(yīng)的模式。
示例
this.signupForm = this.fb.group({
userName: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+_]+@[a-z0-9.-]+')]]
});
動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則
myControl.setValidators(Validators.required); myControl.setValidators([Validators.required, Validators.maxLength(6)]); myControl.clearValidators(); myControl.updateValueAndValidity();
自定義驗(yàn)證器
function myCustomValidator(c: AbstractControl):
{[key: string]: boolean} | null {
if(somethingIsWrong) {
return { 'myvalidator': true};
}
return null;
}
自定義驗(yàn)證器 (支持參數(shù))
function myCustomValidator(param: any): ValidatorFn {
return (c: AbstractControl): {[key: string]: boolean} | null {
if(somethingIsWrong) {
return { 'myvalidator': true};
}
return null;
}
}
跨字段驗(yàn)證
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 })
});
在介紹表單驗(yàn)證前,我們來看一下目前頁面的顯示效果:

表單驗(yàn)證
表單的內(nèi)建驗(yàn)證規(guī)則,前面章節(jié)已經(jīng)介紹過了,接下來我們來介紹在表單中如何 "動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則" 。
動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則
為了演示 "動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則" 的功能,我新增了兩個(gè)控件:
- radio - 用于讓用戶設(shè)置是否開啟手機(jī)登錄。
- tel - 當(dāng)用戶開啟手機(jī)登錄功能,用于讓用戶輸入手機(jī)號碼。
當(dāng)用戶開啟手機(jī)登錄功能,手機(jī)號碼對應(yīng)控件的驗(yàn)證規(guī)則,必須是必填且格式為合法的手機(jī)號碼。當(dāng)用戶不開啟手機(jī)登錄功能時(shí),手機(jī)號碼對應(yīng)控件將不是必填的。
新增 radio 控件
<div class="form-group">
<div class="col-md-offset-1 col-md-8 checkbox">
開啟手機(jī)登錄
<label>
<input type="radio" value="1"
formControlName="enableMobile">
是
</label>
<label>
<input type="radio" value="0"
formControlName="enableMobile">
否
</label>
</div>
</div>
新增 tel 控件
<div class="form-group"
[ngClass]="{'has-error': (mobile.touched || mobile.dirty) && !mobile.valid }">
<label class="col-md-2 control-label"
for="mobileId">手機(jī)號碼</label>
<div class="col-md-8">
<input class="form-control"
id="mobileId"
type="text"
placeholder="請輸入手機(jī)號碼"
formControlName="mobile"/>
<span class="help-block" *ngIf="(mobile.touched || mobile.dirty)
&& mobile.errors">
<span *ngIf="mobile.errors.required">
請輸入手機(jī)號碼
</span>
<span *ngIf="mobile.errors.minlength">
手機(jī)號碼格式不正確
</span>
</span>
</div>
</div>
動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則功能
ngOnInit(): void {
...
this.signupForm.get('enableMobile').valueChanges
.subscribe(value => this.checkMobile(value));
}
checkMobile(enableMobile: string): void {
const mobileControl = this.signupForm.get('mobile');
enableMobile === "1" ?
mobileControl.setValidators([Validators.required,
Validators.pattern('1(3|4|5|7|8)\\d{9}')]) :
mobileControl.clearValidators();
mobileControl.updateValueAndValidity();
}
介紹完如何動(dòng)態(tài)調(diào)整驗(yàn)證規(guī)則,接下來我們來介紹如何 "自定義驗(yàn)證器"。
自定義驗(yàn)證器
為了演示 "自定義驗(yàn)證器" 的功能,我新增了一個(gè)控件:
number - 用于讓用戶設(shè)置是年齡信息。
當(dāng)讓用戶手動(dòng)輸入年齡信息時(shí),我們需要設(shè)置一個(gè)有效的年齡范圍,比如 (18 - 120)。此時(shí)我們就需要通過自定義驗(yàn)證器來實(shí)現(xiàn)上述功能。
新增 number 控件
<div class="form-group"
[ngClass]="{'has-error': (age.touched || age.dirty) && !age.valid }">
<label class="col-md-2 control-label"
for="ageId">年齡</label>
<div class="col-md-8">
<input class="form-control"
id="ageId"
type="number"
placeholder="請輸入年齡"
formControlName="age"/>
<span class="help-block" *ngIf="(age.touched || age.dirty) && age.errors">
<span *ngIf="age.errors.range">
輸入年齡不合法
</span>
</span>
</div>
</div>
自定義驗(yàn)證器模板
function myCustomValidator(c: AbstractControl):
{[key: string]: boolean} | null {
if(somethingIsWrong) {
return { 'myvalidator': true};
}
return null;
}
新增 ageValidator 驗(yàn)證器
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 驗(yàn)證器
ngOnInit(): void {
this.signupForm = this.fb.group({
// ...
age: ['', ageValidator]
});
}
我們的 ageValidator 自定義驗(yàn)證器,雖然已經(jīng)實(shí)現(xiàn)了。細(xì)心的讀者應(yīng)該會(huì)發(fā)現(xiàn),在 ageValidator 驗(yàn)證器內(nèi)部,我們寫死了年齡的邊界值 (最小值與最大值)。理想的情況下,應(yīng)該能夠讓用戶自行設(shè)定邊界值。因此接下來,我們來優(yōu)化一下 ageValidator 驗(yàn)證器。
自定義驗(yàn)證器 (支持參數(shù))
自定義驗(yàn)證器模板 (支持參數(shù))
function myCustomValidator(param: any): ValidatorFn {
return (c: AbstractControl): {[key: string]: boolean} | null {
if(somethingIsWrong) {
return { 'myvalidator': true};
}
return null;
}
}
新增 ageRange 驗(yàn)證器工廠
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 驗(yàn)證器工廠
ngOnInit(): void {
this.signupForm = this.fb.group({
// ...
age: ['', ageRange(20, 120)]
});
}
介紹完如何自定義驗(yàn)證器,接下來我們來介紹如何實(shí)現(xiàn) "跨字段驗(yàn)證" 的功能。
跨字段驗(yàn)證
在日常生活中,在注冊表單中,經(jīng)常要讓用戶再次輸入同樣的字段值,比如登錄密碼或郵箱地址的值。針對這種場景,我們就需要驗(yàn)證兩個(gè)控件的輸入值是否一致,這時(shí)我們就要引入跨字段驗(yàn)證的功能。
為了演示 "跨字段驗(yàn)證" 的功能,我新增了一個(gè)控件:
- email - 用于讓用戶確認(rèn)輸入的郵箱地址
新增 email 控件
<label class="col-md-2 control-label"
for="emailId">確認(rèn)郵箱</label>
<div class="col-md-8">
<input class="form-control"
id="confirmEmailId"
type="email"
placeholder="請?jiān)俅屋斎豚]箱地址"
formControlName="confirmEmail"/>
<span class="help-block" *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 class="form-group"
formGroupName="emailGroup"
[ngClass]="{'has-error': emailGroup.errors }">
<label class="col-md-2 control-label"
for="emailId">郵箱</label>
<div class="col-md-8">
<input class="form-control"
id="emailId"
type="email"
placeholder="請輸入郵箱地址"
formControlName="email"/>
<span class="help-block" *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控件"的內(nèi)容-->
</div>
上面代碼中,有以下幾個(gè)問題需要注意:
- Form Group 是可以嵌套使用的。
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 })
我們通過 formGroupName="groupName" 語法來綁定內(nèi)嵌的 Form Group。
<div class="form-group" formGroupName="emailGroup"
[ngClass]="{'has-error': emailGroup.errors }">
郵箱不匹配的信息是存在 emailGroup 對象的 errors 屬性中,而不是存在 confirmEmail 對象的 errors 屬性中。
<span *ngIf="!confirmEmail.errors?.required && emailGroup.errors?.match"> 兩次輸入的郵箱地址不一致 </span>
我有話說
怎么會(huì)監(jiān)聽表單值的變化?
Reactive Form
export class AppComponent {
constructor(private fb: FormBuilder) {
this.form = fb.group({
name: 'semlinker',
age: 31
});
this.form.valueChanges.subscribe(data => {
console.log('Form changes', data)
});
}
}
Template-driven Form
模板
<form #myForm="ngForm" (ngSubmit)="onSubmit()"> <input type="text" name="name" class="form-control" required [(ngModel)]="user.name"> <input type="number" name="age" class="form-control" required [(ngModel)]="user.age"> </form>
組件類
class AppComponent implements AfterViewInit {
@ViewChild('myForm') form;
ngAfterViewInit() {
this.form.control.valueChanges
.debounceTime(500)
.subscribe(values => this.doSomething(values));
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 淺談vue,angular,react數(shù)據(jù)雙向綁定原理分析
- 前端框架學(xué)習(xí)總結(jié)之Angular、React與Vue的比較詳解
- VueJs與ReactJS和AngularJS的異同點(diǎn)
- React中如何引入Angular組件詳解
- 利用angular、react和vue實(shí)現(xiàn)相同的面試題組件
- 如何將你的AngularJS1.x應(yīng)用遷移至React的方法
- JavaScript框架Angular和React深度對比
- 在React框架中實(shí)現(xiàn)一些AngularJS中ng指令的例子
- 詳解React Angular Vue三大前端技術(shù)
相關(guān)文章
詳解angularjs的數(shù)組傳參方式的簡單實(shí)現(xiàn)
本篇文章主要介紹了angularjs的數(shù)組傳參方式的簡單實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
在 Angular 中實(shí)現(xiàn)搜索關(guān)鍵字高亮示例
本篇文章主要介紹了在 Angular 中實(shí)現(xiàn)搜索關(guān)鍵字高亮示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
AngularJS extend用法詳解及實(shí)例代碼
這篇文章主要介紹了AngularJS extend用法詳解的相關(guān)資料,并附實(shí)例代碼,幫助大家學(xué)習(xí)理解,需要的朋友可以參考下2016-11-11
Angular 輸入框?qū)崿F(xiàn)自定義驗(yàn)證功能
AngularJS 表單和控件可以驗(yàn)證輸入的數(shù)據(jù)。本文給大家介紹Angular 輸入框?qū)崿F(xiàn)自定義驗(yàn)證功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-02-02
AngularJS驗(yàn)證信息框架的封裝插件用法【w5cValidator擴(kuò)展插件】
這篇文章主要介紹了AngularJS驗(yàn)證信息框架的封裝插件用法,分析了AngularJS表單驗(yàn)證規(guī)則并實(shí)例說明了w5cValidator擴(kuò)展插件的相關(guān)使用技巧,需要的朋友可以參考下2016-11-11
AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作示例【附demo源碼下載】
這篇文章主要介紹了AngularJS實(shí)現(xiàn)與Java Web服務(wù)器交互操作的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了AngularJS前臺ajax提交與javascript后臺處理的完整流程與實(shí)現(xiàn)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-11-11

