1.模板式表單css
在html模板上控制html
指令對應的實例react
1.ngForm指令:標記表單,會隱式建立FormGroup類的實例,這個類表明表單數據模型,並存儲表單數據;數組
2.ngModel指令:標記單個字段,ngFrom指令會發現含有ngModel指令的標籤,並添加到表單數據模型中,使用該指令必須跟隨name屬性;瀏覽器
3.ngModelGroup指令:標記多個字段組合,表現形式是一個對象,如{name:"張三",pass:"123"};服務器
例子:app
<!--模板變量myForm指向ngForm對象--> <form #myForm = "ngForm" (ngSubmit) = "onSubmit(myForm.value)"> <div>用戶名:<input ngModel type="text" name="username"/></div> <!--ngModelGroup將字段嵌套成一個組--> <div ngModelGroup="passwordGroup"> <div>密碼:<input ngModel type="password" name="password"/></div> <div>確認密碼:<input ngModel type="password" name="confirmPass"/></div> </div> <div>電話:<input ngModel type="text" name="mobile"/></div> <div><input type="submit" value="提交"/></div> </form>
結果:異步
2.響應式表單angular4
在ts上控制表單數據,可用於動態生成表單ide
類對應的指令
formGroup:標記組,表單也屬於組,屬於屬性指令,須要加 [ ]
formGroupName:標記組,用於formGroup指令範圍內部。
formControl:標記字段,屬於屬性指令,須要加 [ ],用於在formGroup指令範圍外部。
formControlName:標記字段,用於formGroup指令範圍內部。
formArrayName:標記數組,用於formGroup指令範圍內部。
例子:
reactiveForm.html
<form [formGroup]="formModel" (submit)=onSubmit() novalidate> <div formGroupName="dateRange"> 起始日期:<input type="date" formControlName="from"> 截止日期:<input type="date" formControlName="to"> </div> <div> <ul formArrayName="emails"> <!-- 循環formArray數組,和下標 --> <li *ngFor="let e of this.formModel.get('emails').controls; let i=index;"> <!-- formArray沒有key,全部使用屬性綁定[],值爲數組的下標 --> <input type="text" [formControlName]="i"> </li> </ul> <button type="button" (click)="addEmail()">增長Email</button> </div> <button type="submit">保存</button> </form> <input type="text" [formControl]="username">
reactiveForm.ts
import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup, FormArray } from '@angular/forms/src/model'; @Component({ selector: 'app-reactive-form', templateUrl: './reactive-form.component.html', styleUrls: ['./reactive-form.component.css'] }) export class ReactiveFormComponent implements OnInit { //定義數據模型 formModel : FormGroup = new FormGroup({ dateRange : new FormGroup({ from:new FormControl(), to:new FormControl() }), emails : new FormArray([ new FormControl("a@aa.com"), new FormControl("b@bb.com"), ]) }); username:FormControl=new FormControl("張三"); constructor() {} ngOnInit() {} onSubmit(){ console.log(this.formModel.value); } addEmail(){ let emails=this.formModel.get("emails") as FormArray; emails.push(new FormControl()); } }
也能夠使用FormBuilder類來建立數據模型,上面代碼改爲:
formModel : FormGroup; constructor(fb:FormBuilder){ //定義數據模型 this.formModel = fb.group({ dateRange : fb.group({ from:[''], to:[''] }), emails : fb.array([ ["a@aa.com"], ["b@bb.com"], ]) });
3.響應式表單校驗
angular4提供了validator類的預約義校驗:
required - 設置表單控件值是非空的
email - 設置表單控件值的格式是 email
minlength - 設置表單控件值的最小長度
maxlength - 設置表單控件值的最大長度
pattern - 設置表單控件的值需匹配 pattern 對應的模式
固然,也能夠進行自定義校驗
例子:
reactiveForm.html
<form [formGroup]="formModel" (ngSubmit) = "onSubmit()" novalidate> <div>用戶名:<input formControlName="username"/></div> <!-- 當驗證經過或者未點擊該字段時隱藏,狀態字段untouched=true表示未點擊,touched=true表示已點擊 --> <div [hidden]="formModel.get('username').valid || formModel.get('username').untouched"> <!-- 1.在模板上硬編碼錯誤信息 --> <!-- [hidden]=false表示顯示錯誤信息,hasError(校驗失敗返回對象的key,校驗字段的name) --> <div [hidden]="!formModel.hasError('required','username')"> 用戶名是必填項 </div> <div [hidden]="!formModel.hasError('minLength','username')"> 用戶名最小長度6 </div> </div> <div formGroupName="passwordsGroup"> <div>密碼:<input formControlName="password"/></div> <!-- 包含在group中的hasError第二個參數爲數組[groupname,controlname] --> <div [hidden]="!formModel.hasError('minLength',['passwordsGroup','password'])"> 密碼最小長度是6 </div> <div>確認密碼:<input formControlName="pconfirm"/></div> <div [hidden]="!formModel.hasError('equal','passwordsGroup')"> {{formModel.getError('equal',passwordsGroup)?.passErrDesc}} </div> </div> <div>電話:<input formControlName="mobile"/></div> <!-- 當驗證沒有經過或者未改變該字段值時顯示 狀態字段pristine=ture表示未改變,dirty=ture表示已改變--> <div [hidden]="formModel.get('mobile').valid || formModel.get('username').pristine"> <!-- 2.動態錯誤提示 --> <div [hidden]="!formModel.hasError('mobile','mobile')"> {{formModel.getError('mobile')?.mobileErrDesc}} </div> </div> <div><input type="submit" value="提交"/></div> </form>
reactiveForm.ts
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms/src/model'; import { FormBuilder,Validators} from '@angular/forms'; @Component({ selector: 'app-reactive-form2', templateUrl: './reactive-form2.component.html', styleUrls: ['./reactive-form2.component.css'] }) export class ReactiveForm2Component implements OnInit { formModel:FormGroup; /** * 自定義手機號校驗 * 返回值:正確返回 null * 錯誤返回 key:value(value能夠是對象錯誤key:錯誤信息,也能夠是任意值) * @param control */ mobileValidator(control:FormControl):any{ var myreg = /^((0\d{2,3}-\d{7,8})|(1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}))$/; let valid = myreg.test(control.value); console.log("mobile的校驗結果是"+valid); return valid ? null : {mobile:{mobileErrDesc:"密碼和確認密碼不匹配"}}; } //自定義密碼組校驗 equalValidatir(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("密碼校驗結果:"+valid); return valid ? null :{equal:{passErrDesc:"密碼和確認密碼不匹配"}}; } constructor(fb:FormBuilder) { //定義數據模型 this.formModel = fb.group({ //預約義校驗 username:['',[Validators.required,Validators.minLength(6)]], mobile:['',this.mobileValidator], passwordsGroup:fb.group({ password:[''], pconfirm:[''] },{validator:this.equalValidatir}) }); } ngOnInit() {} onSubmit(){ //整個表單校驗經過 if(this.formModel.valid){ console.log(this.formModel.value); } } }
固然,有些校驗方法時通用的,因此咱們能夠提取出全局的校驗方法。
須要function聲明該方法,再經過 export 關鍵字暴露該方法。
validator.ts
import { FormControl, FormGroup } from "@angular/forms"; //自定義手機號碼組校驗 export function mobileValidator(control:FormControl):any{ var myreg = /^((0\d{2,3}-\d{7,8})|(1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}))$/; let valid = myreg.test(control.value); console.log("mobile的校驗結果是"+valid); return valid ? null : {mobile:{mobileErrDesc:"密碼和確認密碼不匹配"}}; } //自定義密碼組校驗 export function equalValidatir(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("密碼校驗結果:"+valid); return valid ? null :{equal:{passErrDesc:"密碼和確認密碼不匹配"}}; }
異步校驗器
用來調用遠程的服務來校驗表單的值。異步校驗器跟普通的校驗器同樣,只不過返回的是一個可觀測的流。
例子:
validator.ts
import { FormControl, FormGroup } from "@angular/forms"; //自定義手機號碼組校驗 export function mobileAsyncValidator(control:FormControl):any{ var myreg = /^((0\d{2,3}-\d{7,8})|(1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}))$/; let valid = myreg.test(control.value); console.log("mobile的校驗結果是"+valid); //Observable.of返回一個流,.delay(5000)表示延遲5秒,用來模擬服務器響應時間 return Observable.of(valid ? null : {mobile:{mobileErrDesc:"密碼和確認密碼不匹配"}}).delay(5000); }
reactiveForm.ts
constructor(fb:FormBuilder) { //定義數據模型 this.formModel = fb.group({ //預約義校驗 username:['',[Validators.required,Validators.minLength(6)]], //異步校驗做爲第3個構造函數 mobile:['',this.mobileValidator,this.mobileAsyncValidator], passwordsGroup:fb.group({ password:[''], pconfirm:[''] },{validator:this.equalValidatir}) }); }
<!--狀態字段pending=true表示正在進行校驗--> <div [hidden]="!formModel.get('mobile').pending"> 正在校驗手機合法性 </div>
4.模板式表單校驗
終端輸入命令$ ng g directive directive/mobileValidator 建立指令文件
將校驗方法定義成指令,以下
mobileValidator.directive.ts
import { Directive } from '@angular/core'; import { NG_VALIDATORS } from '@angular/forms'; import { mobileValidator } from '../validator/validator'; //指令裝飾器 @Directive({ selector: '[mobile]',//指令名稱 //useValue:校驗方法名稱 ,multi:true:表示token爲NG_VALIDATORS的提供器可對應多個useValue providers:[{provide:NG_VALIDATORS,useValue:mobileValidator,multi:true}] }) export class MobileValidatorDirective { constructor() { } }
在模板中使用指令來校驗模板表單
templateForm.component.html
<!-- novalidate指令:不啓用瀏覽器默認的表單校驗,讓angualr的校驗指令不受干擾 --> <form #myForm = "ngForm" (ngSubmit) = "onSubmit(myForm.value,myForm.valid)" novalidate> <!-- 使用angular預約義的指令required,minlength等來校驗表單 --> <div>用戶名:<input ngModel required minlength="6" name="username" type="text"/></div> <div ngModelGroup="passwordGroup" equal> <div>密碼:<input ngModel type="password" name="password"/></div> <div>確認密碼:<input ngModel type="password" name="confirmPass"/></div> </div> <!-- 定義input事件來控制是否顯示錯誤提示 --> <div>電話:<input ngModel mobile name="mobile" type="text" (input)="onMobileInput(myForm)"/></div> <!-- 接收模板的值判斷是否顯示錯誤提示 --> <div [hidden]="mobileValid || mobileUntouched"> <!-- 使用myForm.form獲取表單對象 --> <div [hidden]="!myForm.form.hasError('mobile','mobile')"> 電話號碼不正確 </div> <div> <div><input type="submit" value="提交"/></div> </form>
templateForm.component.ts
import { Component, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms/src/directives/ng_form'; @Component({ selector: 'app-template-form', templateUrl: './template-form.component.html', styleUrls: ['./template-form.component.css'] }) export class TemplateFormComponent implements OnInit { constructor() { } ngOnInit() {} mobileValid:boolean=true; mobileUntouched:boolean=true; //點擊電話輸入框時,判斷mobile是否合法 onMobileInput(form:NgForm){ if(form){ this.mobileValid = form.form.get("mobile").valid; this.mobileUntouched = form.form.get("mobile").untouched; } } onSubmit(value:any,valid:boolean){ console.log(valid); console.log(value); } }