表單校驗 Angular的校驗器
- angular提供了一組預(yù)定義的校驗器,這些校驗器都是定義在angular的form模塊中的Validators類中(required,minLength,maxLength,pattern校驗器)
- 校驗username,校驗為必填,最小長度為6,獲取校驗結(jié)果,如夠有一項不符合則為false,返回false時獲取錯誤信息
username:['',[Validators.required,Validators.minLength(6)]],
let isValid:boolean=this.formModel.get("username").valid;
console.log('username校驗結(jié)果:'+isValid);
let errors:any=this.formModel.get("username").errors;
console.log('username錯誤信息:'+JSON.stringify(errors));
自定義校驗器
xxxx(control:AbstractControl):{[key:string]:any}{
return null;
}
- 定義一個驗證手機的校驗器mobileValidator,mobile字段的類型為FormControl,然后返回一個任意類型的對象,寫一個正則表達式來校驗手機號(校驗手機號是否以13,15,18開頭,同時限定長度),并在mobile字段中使用這個校驗器,校驗成功返回為null,失敗返回為mobile:true(mobile是key)
mobileValidator(control:FormControl):any{
var myreg=/^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
let valid=myreg.test(control.value);
console.log("mobile校驗結(jié)果"+valid);
return valid?null:{mobile:true};
}
mobile:['',this.mobileValidator],
-
每次改變手機號時這個方法都會被調(diào)用,檢查當前的值是否為合法的
- 自定義一個重復(fù)密碼校驗器,校驗兩次輸入的密碼是否相同
equalValidator(group:FormGroup):any{
let password:FormControl=group.get("password") as FormControl;
let pconfirm:FormControl=group.get("pconfirm") as FormControl;
let valid:boolean=(password.value===pconfirm.value);
console.log("密碼校驗結(jié)果"+valid);
return valid?null:{equal:true};
passwordsGroup: fb.group({
password:[''],
pconfirm:[''],
},{validator:this.equalValidator})
- 校驗器的方法不一定要寫在組件中,它可以單獨提取出去,寫在一個單獨的ts文件中,并通過export關(guān)鍵字將 其暴露出來,這樣就可以將應(yīng)用中通用的校驗器寫在一個文件中,在不同的組件中復(fù)用
- 在app文件夾下新建一個validator文件,并新建一個validators.ts文件用來存放校驗器,將組剪切到這個文件中,這時它們不在是一個ts類中的方法了,而是全局的ts函數(shù),用function聲明再用export暴露出去
import {FormControl, FormGroup} from '@angular/forms';
export function mobileValidator(control:FormControl):any{
var myreg=/^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
let valid=myreg.test(control.value);
console.log("mobile校驗結(jié)果"+valid);
return valid?null:{mobile:true};
}
export function equalValidator(group:FormGroup):any{
let password:FormControl=group.get("password") as FormControl;
let pconfirm:FormControl=group.get("pconfirm") as FormControl;
let valid:boolean=(password.value===pconfirm.value);
console.log("密碼校驗結(jié)果"+valid);
return valid?null:{equal:true};
}
- 這樣實際上是聲明了兩個全局的方法,在組件中可以直接使用import引入這兩個全局的方法后直接使用
校驗響應(yīng)式表單
- 校驗失敗時顯示錯誤信息,使用.hasError方法,接收兩個參數(shù),第一個參數(shù)是希望校驗的錯誤(required,不是校驗器的名字,而是校驗器失敗時返回的對象的key),第二個字段是要檢查的字段的名字,當username的required校驗不通過時返回一個true,所以hidden要取反(當兩個校驗都不成功時,優(yōu)先判斷是否填寫,因此只顯示第一項信息)
<form [formGroup]="formModel" (submit)="onSubmit()">
<div>用戶名:<input type="text" formControlName="username"></div>
<div [hidden]="!formModel.hasError('minlength','username')">
用戶最小長度為6
</div>
<div [hidden]="!formModel.hasError('required','username')">
用戶名是必填項
</div>
<div>手機號:<input type="number" formControlName="mobile"></div>
<div [hidden]="!formModel.hasError('mobile','mobile')">
請輸入正確的mobile
</div>
<div formGroupName="passwordsGroup">
<div>密碼:<input type="password" formControlName="password"></div>
<div>確認密碼:<input type="password" formControlName="pconfirm"></div>
</div>
<div [hidden]="!formModel.hasError('equal','passwordsGroup')">
密碼不匹配
</div>
<button type="submit">注冊</button>
</form>
- 因為password字段是嵌套在passwordsGroup中的,所以在這個hasError方法中的第二個參數(shù)必須為一個數(shù)組,這個數(shù)組第一個數(shù)據(jù)為passwordsGroup第二個數(shù)據(jù)才是需要校驗的字段password
- 校驗器可以提供需要輸出的錯誤信息,在校驗器的錯誤返回中輸入需要提示的信息{equal:{descxx:'密碼不匹配'}},再通過getError來獲取
export function equalValidator(group:FormGroup):any{
let password:FormControl=group.get("password") as FormControl;
let pconfirm:FormControl=group.get("pconfirm") as FormControl;
let valid:boolean=(password.value===pconfirm.value);
console.log("密碼校驗結(jié)果"+valid);
return valid?null:{equal:{descxx:'密碼不匹配'}};
}
<div formGroupName="passwordsGroup">
<div>密碼:<input type="password" formControlName="password"></div>
<div>確認密碼:<input type="password" formControlName="pconfirm"></div>
</div>
<div [hidden]="!formModel.hasError('equal','passwordsGroup')">
{{formModel.getError('equal','passwordsGroup')?.descxx}}
</div>
異步校驗器
- Angular的API還支持一個特殊的校驗器:異步校驗器,可以用來調(diào)用遠程的服務(wù)來檢查表單的值,與普通的校驗器類似,異步校驗器也是一個方法,但是異步校驗器返回的不是一個對象,而是一個可觀測的流
- 在返回時將返回值放入一個流Observable.of中返回,使用delay延遲5秒返回模擬在服務(wù)器請求數(shù)據(jù)的效果,在輸入手機號是完成了本地校驗器的校驗后,表單的狀態(tài)會從INVALID變成PENDING 5秒鐘,然后 變成VALID,PENDING狀態(tài)就是調(diào)用遠程的服務(wù)去校驗當前的手機號,還不能確定是否正確
export function mobileAsvncValidator(control:FormControl):any{
var myreg=/^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
let valid=myreg.test(control.value);
console.log("mobile校驗結(jié)果"+valid);
return Observable.of(valid?null:{mobile:true}).delay(5000);
}
mobile:['',mobileValidator,mobileAsvncValidator],
狀態(tài)字段
- 在一開始初始化后用戶名字段就是非法的,但是用戶并沒有訪問 過這個字段,不應(yīng)該顯示這個錯誤信息給用戶,為了解決這些問題angular提供了狀態(tài)字段
- touched和untouched:用來判斷用戶是否訪問過一個字段(也就是一個字段是否獲取過焦點)
<div>用戶名:<input type="text" formControlName="username"></div>
<div [hidden]="formModel.get('username').valid || formModel.get('username').untouched">
<div [hidden]="!formModel.hasError('required','username')">
用戶名是必填項
</div>
<div [hidden]="!formModel.hasError('minlength','username')">
用戶最小長度為6
</div>
</div>
- pristine和dirty:如果一個字段的值沒有被改變過pristine為true
- pending:當一個字段處于異步校驗時,字段的pending屬性為true
<div>手機號:<input type="number" formControlName="mobile"></div>
<div [hidden]="!formModel.get('mobile').pending">
正在校驗手機號合法性
</div>
- 狀態(tài)字段還可以用于綁定css樣式,這個字段無效并且被訪問過時會修改為這個樣式
<div>用戶名:<input [class.hasError]="formModel.get('username').invalid && formModel.get('username').touched" type="text" formControlName="username">
</div>