在上一篇文章中提到了表單,只說了表單的數據綁定,這一篇文章主要講一下表單驗證,為什么把表單單獨拿出來學習,主要是因為,表單是商業應用的支柱,我們用它來執行登錄、求助、下單、預訂機票、安排會議,以及不計其數的其它數據錄入任務,使用頻率非常高。所以這塊的重要性就顯而易見了。
正文開始,這篇文章還是適合初學者,如果是大神,請指正不足:
先來看一下最終的樣子:
表單很簡單,模擬新增客戶,用到表單的不少控件,
首先,要使用angular 的表單的一些控件,在使用ngModel
做雙向數據綁定之前,得先導入FormsModule
, 把它加入 Angular 模塊的imports
列表。
在加載之前寫組件。app.module.ts主文件代碼如下:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; //引入表單模塊 import { AppComponent } from './app.component'; import { UserForm } from './form.component'; // 引入自定義的組件 @NgModule({ imports: [ BrowserModule ,FormsModule], declarations: [ AppComponent,UserForm], bootstrap: [ AppComponent ] }) export class AppModule { }
下面我們主要看一下表單這個組件內部的一些細節:
1 import { Component } from '@angular/core'; 2 3 @Component({ 4 selector:'hero-form', 5 template:` 6 <h2>FORM 表單</h2> 7 <hr /> 8 <div class="container"> 9 <div class="row"> 10 <div class="col-sm-6 col-sm-offset-3"> 11 <h4>客戶管理</h4> 12 <form #forms="ngForm"> 13 <div class="alert alert-danger" [hidden]="forms.form.valid">表單填寫不合法</div> 14 <div class="form-group"> 15 <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label> 16 <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required> 17 </div> 18 <div class="form-group"> 19 <label [class.text-danger]="!sex.valid && forms.form.controls.sex.touched">性別</label> 20 <select class="form-control" [(ngModel)]="model.sex" required name="sex" #sex="ngModel"> 21 <option *ngFor="let s of sexs" [ngValue]="s">{{s}}</option> 22 </select> 23 </div> 24 <div class="form-group"> 25 <label>來源</label> 26 <div> 27 <label class="checkbox-inline" *ngFor="let f of froms"> 28 <input type="radio" [value]="f" name="from" [(ngModel)]="model.from" #from="ngModel" required> {{f}} 29 </label> 30 </div> 31 </div> 32 <div class="form-group"> 33 <label>意向產品</label> 34 <div> 35 <label class="checkbox-inline" *ngFor="let p of model.mayBuy"> 36 <input type="checkbox" [(ngModel)]="p.chose" [value]="p.pid" name="mayBuy" required> {{p.pname}} 37 </label> 38 </div> 39 </div> 40 <button type="button" (click)="submit(forms.form)" [class.btn-danger]="!forms.form.valid" [disabled]="!forms.form.valid" class="btn btn-primary">提交</button> 41 </form> 42 </div> 43 </div> 44 </div> 45 ` 46 }) //這里有個小坑,如果這里按習慣加一個分號“;”,那就掛了,不能編譯 47 48 export class UserForm { 49 sexs = ['男', '女','保密']; 50 products = [ 51 { 52 pid:'p_001', 53 pname:'產品A', 54 chose:false 55 }, 56 { 57 pid:'p_001', 58 pname:'產品B', 59 chose:false 60 }, 61 { 62 pid:'p_001', 63 pname:'產品C', 64 chose:false 65 }, 66 { 67 pid:'p_001', 68 pname:'產品D', 69 chose:false 70 } 71 ]; 72 froms = ['新增客戶','老客戶介紹']; 73 model = { 74 name:'', 75 sex:'', 76 from:'', 77 mayBuy:this.products 78 }; 79 submitted = false; 80 81 submit(a:any){ 82 console.log(this.model,a) 83 } 84 }
普通表單結構以及數據的雙向綁定,就不多說了,主要說一下表單驗證這塊,即紅色代碼的地方。
交代一下基礎概念,在ng 的表單模塊中,單個控件(如:input)都會被跟蹤狀態,並且會在該控件上增加相應的class:
1)、控件是否已經被訪問過:
是:touched;class:ng-touched
否:untouched; class:ng-untouched
2)、控件的值是否被修改過:
是:dirty;class:ng-dirty
否:pristine;class:ng-pristine
3)、控件的值是否合法:
是:valid;class:ng-valid
否:invalid;class:ng-invalid
整體表單也存在以上的3中狀態,表單的驗證證是通過這些跟蹤的不同狀態完成的。那么怎么訪問到這些狀態呢?
你可能已經注意到在form標簽上有這樣一段代碼:
<form #forms="ngForm">
是的,#forms這個就是模版引用變量,上一篇文章提到過,這里只是把#forms初始化為 "ngForm";
現在我們就可以通過forms這個對象訪問到我們需要的狀態了,如果你不知道forms里都有啥,怎么用,那你就寫個方法,把它打印出來,(click)="submit(forms)" 就可以了。
還有一個要注意的點,就是針對類似
<input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
這樣的,name屬性是必須要添加的,如果要對單個控件進行驗證,我們可以加上模版引用變量#name="ngModel"快速訪問到這個控件。
如果你需要正則表達式驗證,只需加入pattern屬性即可;
<input type="text" class="form-control" pattern="[a-zA-Z ]*" [(ngModel)]="model.name" name="name" />
以上述代碼為例主要有以下幾個點:
1、整體表單的合法性驗證:
代碼:forms.form.STATE,例如:forms.form.valid;forms.form.invalid
2、單個表單控件驗證:
以這段代碼為例:
1 <div class="form-group"> 2 <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label> 3 <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required> 4 </div>
這里的label的顯示樣式的判斷條件其實是兩種判斷方法,
1)、!name.valid這個是使用模板引用變量來判斷的;
2)、forms.form.controls.name.touched是使用forms.form這個對象判斷的。
注意:forms.form這個對象里有很多子對象,這里使用的是form下controls這個對象查找到name判斷的,至於是否應該controls這個子對象,有待研究。
本文到此結束,只是表單的一些初級應用,如果想了解更多,請點擊這里查看API文檔。
歡迎大家對本文所涉及的內容進行探討,對有誤的地方進行指正。
感謝閱讀。