ng2表單

angular提供了模板驅動和模型驅動兩種方式來構建表單。模板驅動模式使用模板表單內置指令、內置校驗的方式來構建表單;模型驅動模式采用自定義表單、自定義校驗的方式來構建表單。

表單指令

NgForm指令

NgForm指令是表單的控制中心,負責處理表單內的頁面邏輯,為普通的表單元素擴充了許多額外的特性,所有的表單指令都需要在NgForm指令內部才能正常運行。
首先要在根模塊中添加FormsModule

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { FormComponent } from './form.component';
@NgModule({
    imports:[
        BrowserModule,
        FormsModule  //導入FormsModule
    ],
    declarations:[
        AppComponent,
        FormComponent
    ],
    bootstrap:[AppComponent]
})
export class AppModule {}

可以不用在模板中顯式的使用NgForm指令,因為添加了FormsModule模塊后,angular模板在編譯解析時,遇到<form>標簽會自動創建一個NgForm指令并且將其添加到該<form>標簽上。

NgModel指令

angular表單支持單向和雙向數據綁定,表單的單向數據綁定使用[ngModel],雙向數據綁定使用[(ngModel)]

<input type="text" name="contactName" [ngModel]="curContact.name" />
<input type="text" name="contactName" [(ngModel)]="curContact.name" />

在控件中使用NgModel屬性綁定,必須給該控件添加name屬性,否則會報錯。因為NgForm指令會為表單建立一個控件對象FormControl的集合,以此來作為表單控件的容器。控件的NgModel屬性綁定會以name作為唯一標識符來注冊并生成一個FormControl,將其加入到FormControl的集合中。

常用的表單控件:

單選框:單選框控件實現雙向數據綁定,同一組單選框控件的所有[(ngModel)]屬性都必須綁定同一個模型數據,且name屬性名也必須相同。

<input type="radio" name="sex" [(ngModel)]="curContact.sex" value="female" />女
<input type="radio" name="sex" [(ngModel)]="curContact.sex" value="male" />男

當單擊選項為“女”的單選框,curContact.sex會被賦值為female,若單擊“男”單選框,則所對應的值為male
復選框:復選框控件用來表示該表單復選框是否被選中,其中[(ngModel)]屬性綁定的是一個布爾值。

<input type="checkbox" name="lock" [(ngModel)]="curContact.lock" />禁用

如果復選框被選中,則curContact.lock的值為true,否則為false
單選下拉框:單選下拉框控件的雙向數據綁定需結合option元素綁定的值來實現。option選項的元素屬性的綁定目標有兩種,分別為valuengValue。當在option元素中使用value綁定數據時,其返回值類型是基本數據類型;當使用ngValue綁定數據時,其返回值類型是對象數據類型。

//定義下拉框所需所需數據
export class FormComponent {
    interests:any[]=[
        {value:'reading',display:'閱讀'},
        {value:'traveling',display:'旅游'},
        {value:'sport',display:'運動'}
    ];
}

<select name="interestValue" [(ngModel)]="curContact.interestValue">
    <option *ngFor="let interest of interests" [value]="interest.value">
        {{interest.display}}
    </option>
</select>

例子中,使用[value]來綁定下拉選項的value屬性值,如果選中下拉選項框中的“旅游”項,那么curContact.interestValue的值將變為traveling
單選框被選中后也可以返回對象類型的數據。

<select name="interestObj" [(ngModel)]="curContact.interestObj">
    <option *ngFor="let interest of interests" [ngValue]="interest">
        {{interest.display}}
    </option>
</select>

當選中某個項目后,該下拉框最終返回一個Object類型的對象數據。如選中“旅游”項,則curContact.interestObj的值為{value:'traveling',display:'旅游'}
多選下拉框:實現了下拉選擇多個選項的功能,返回的數據是一個由所有被選項數據組成的數組。

<select multiple name="interestMul" [(ngModel)]="curContact.interestMul">
    <option *ngFor="let interest of interests" [value]="interest.value">
        {{interest.display}}
    </option>
</select>

多選下拉框使用[value]來綁定下拉選項的value屬性值,如果在多選下拉框中選中“旅游”和“運動”兩項,則curContact.interestMul返回值為["traveling","sport"]
多選下拉框還可以使用[ngValue]來綁定下拉選項的value屬性值,如果在多選下拉框中選中“旅游”和“運動”兩項,那么curContact.interestMul返回的數組對象為[{value:'traveling',display:'旅游'},{value:'sport',display:'運動'}]

模板局部變量

模板局部變量是模板中對DOM元素或指令(包括組件)的引用,可以使用在當前元素、兄弟元素或任何子元素中。

DOM元素局部變量

若在標簽元素中定義DOM元素局部變量,只需在其局部變量名前加上#或用ref-前綴。

<li>
    <label for="name">姓名:</label>
    <input type="text" #contactName name="contactName" id="contactName" />
    <input type="number" ref-telNum name="telNum" id="telNum" />
    <p>{{contactName.value}}--{{telNum.value}}</p>
</li>

angular會自動把局部變量設置為對當前DOM元素對象的引用,如上面的局部變量contactName引用的是document.getElementById("contactName")對象。在模板中定義局部變量后,可以直接在模板的其他元素中使用該元素的DOM屬性,如contactName.valuetelNum.value

表單指令局部變量

表單指令也可以定義局部變量,其引用方式與DOM元素局部變量的引用方式不同。表單指令的局部變量在定義時需手動初始化為特定指令的代表值,最終解析后會被賦值為表單指令實例對象的引用。

NgForm表單局部變量
<form #contactForm="ngForm">
    <ul>
        <li>
            <label for="contactName">姓名:</label>
            <input type="text" name="contactName" [(ngModel)]="curContact.name" />
        </li>
        <li>
            <label for="telNum">電話:</label>
            <input type="text" name="telNum" [(ngModel)]="curContact.telNum" />
        </li>
    </ul>
</form>

局部變量contactFormNgForm指令實例對象的引用,可以在模板中讀取NgForm實例對象的屬性值,如追蹤表單的valid屬性狀態。當被包含的所有控件都有效時,contactForm.valid的值為true,否則為false。在控件中添加ngModelname屬性后,若往姓名控件中輸入“李四”,電話控件輸入“123456789”,則contactForm.value的值為:

{
    name:"李四",
    telNum:"123456789"
}
NgModel控件局部變量
<input type="text" name="contactName" [(ngModel)]="curContact.name"
    #contactName="ngModel" />
<p>{{contactName.valid}}</p>

局部變量contactName是對NgModel指令實例對象的引用,可以在模板中讀取NgModel實例對象的屬性值,如通過contactName.valid可追蹤控件狀態、表單校驗不通過時提示錯誤信息。

表單狀態

表單NgFormNgNodel指令都可以用于追蹤表單狀態來實現數據校驗。表單NgFormNgModel指令都有五個表示狀態的屬性,屬性值都為布爾類型,并都可通過對應的局部變量獲取。NgForm追蹤的是整個表單控件的狀態,NgModel追蹤的是其所在表單控件的狀態。

表單狀態屬性語義表

NgModelGroup指令

NgModelGroup指令可以對表單輸入內容進行分組,方便我們在語義上區分不同類型的輸入。

<form #concatForm="ngForm">
    <fieldset ngModelGroup="nameGroup" #nameGroup="ngModelGroup">
        <label>姓:</label>
        <input type="text" name="firstname" [(ngModel)]="curContact.firstname" required />
        <label>名字:</label>
        <input type="text" name="lastname" [(ngModel)]="curContact.lastname" required />
    </fieldset>
    <fieldset ngModelGrooup="addressGroup" #addressGroup="ngModelGroup">
        <label>街:</label>
        <input type="text" name="street" [(ngModel)]="curContact.street" required />
        <label>區:</label>
        <input type="text" name="zip" [(ngModel)]="curContact.zip" required />
        <label>城市:</label>
        <input type="text" name="city" [(ngModel)]="curContact.city" required />
    </fieldset>
</form>

concatForm.value的值為:

{
    nameGourp:{
        firstname:'',
        lastname:''
    },
    addressGroup:{
        street:'',
        zip:'',
        city:''
    }
}

NgModelGroup實例對象的valid屬性可以單獨校驗其所在分組控件的輸入是否有效。如上例中只有當curContact.firstnamecurContact.lastname輸入都有效時,局部變量nameGroup.valid才會變成true,否則為false

ngSubmit事件

ngSubmit事件可以響應表單里類型為submit的按鈕操作,并負責控制表單的提交流程。當按鈕被單機后,會觸發表單的ngSubmit事件。

<form #contactForm="ngForm" (ngSubmit)="doSubmit(contactForm.value)">
    <li class="form-group">
        <button type="submit" class="btn btn-default" [disabled]="!contactForm.valid">添加</button>
        <button type="reset" class="btn btn-default">重置</button>
    </li>
</form>

export class FormComponent{
    doSubmit(formValue:any){
        //處理表單數據并提交
    }
}

ngSubmit事件的類型是EventEmitter。當提交按鈕被點擊后,首先執行表單原生的onSubmit事件,接著執行FormComponent組件中定義的doSubmit()方法,該方法接收contactForm.value的值作為參數傳入,并對傳入的數據進行處理。

自定義表單樣式

NgModel指令不僅能追蹤表單控件的狀態,還會根據表單控件的狀態使用對應的CSS狀態類來更新表單控件的類名。表單控件包括6個CSS狀態類。

控件CSS狀態類名

表單控件的CSS類名會根據表單控件狀態變化而變化。

.ng-valid[required]{
    border-left:5px solid #0f0;
}
.ng-valid{
    border-left:5px solid #f00;
}

還可結合控件的狀態屬性validpristinedirtytoucheduntouched等來添加有用的消息提示,以此來對用戶進行有效的引導。

<div class="form-group">
    <label for="contactName">姓名:</label>
    <input type="type" class="form-control" minlength=3 maxlength=10
        [(ngModel)]="curContact.name" name="contactName"
        #contactName="ngModel" required />
    <p [hidden]="contactName.valid||contactName.pristine" class="alert alert-invalid">
        用戶名長度3-10個字符
    </p>
</div>

表單校驗

表單內置校驗

angular支持的表單內置校驗包括:

  • required:判斷表單控件值是否為空
  • minlength:判斷表單控件值的最小長度
  • maxlength:判斷表單控件值的最大長度
  • pattern:判斷表單控件值的匹配規則
<input type="text" minlength=3 maxlength=10 [(ngModel)]="curContact.name" name="contactName" required />

可以在<form>標簽中添加novalidate屬性來屏蔽HTML的攔截校驗。

表單自定義校驗

創建自定義校驗

下面定義一個用戶名的校驗器,校驗規則為:用戶名必須是郵箱、手機號碼的格式。

//validate-username.ts
import { FormControl } from '@angular/forms';
const EMAIL_REGEXP=new RegExp("[a-z0-9]+@[a-z0-9]+.com");
const TEL_REGEXP=new RegExp("1[0-9]{10}");
export function validateUserName(c:FormControl){
    return (EMAIL_REGEXP.test(c.value)||TEL_REGEXP.test(c.value))?null:{
        userName:{
            valid:false,
            errorMsg:'用戶名必須是手機號或郵箱帳號'
        }
    }
}

自定義校驗函數傳入的參數是FormControl類,通過對FormControlvalue值進行校驗處理,返回校驗結果。

使用自定義校驗

使用模型驅動方式構建表單,需在表單組件所在的模塊代碼中導入ReactiveFormsModule,并在模塊的@NgModule元數據imports數組中加入ReactiveFormsModule

import { ReactiveFormsModule } from '@angular/forms';
import { FormComponent } from './form.component';
import { AppComponent } from './app.component';
@NgModule({
    imports:[BrowserModule,ReactiveFormsModule],
    declarations:[AppComponent,FormComponent],
    bootstrap:[AppComponent]
})
export class AppModule {}

導入ReactiveFormsModule后,可在表單組件FormComponent中使用模型驅動方式構建表單。

import { Component } from '@angular/core';
import { FormGroup,FormControl } from '@angular/forms';
import { validateUserName } from './validate-username';
@Component({
    selector:'add-contact',
    template:`
        <form [formGroup]="customForm">
            <label>姓名:</label>
            <input type="text" formControlName="customName" />
        </form>
    `
})
export class FormComponent{
    customForm=new FormGroup({
        customName:new FormControl('',validateUserName)
    });
}

在構建FormControl實例對象customName時傳入的參數中,第一個參數為控件返回值的初始值,第二個參數為該控件的校驗配置方法。
此外,校驗配置可以使用Validators的內置校驗,如Validators.required()等,這與直接在表單控件元素中添加required屬性效果一致。使用Validators內置校驗,需先從@angular/forms導入Validators

import { Validators } from '@angular/forms';
customForm=new FormGroup({
    customName:new FormControl('',Validators.minLength(4))
});

如果需要在一個表單中添加多個校驗器,可以在校驗配置參數中使用數組,數組元素為對應的校驗方法。

customForm=new FormGroup({
    customName:new FormControl('',[Validators.minLength(4),ValidateUserName])
});
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容

  • 版本:Angular 5.0.0-alpha 表單是商業應用的支柱,我們用它來執行登錄、求助、下單、預訂機票、安排...
    soojade閱讀 1,287評論 0 1
  • 《ijs》速成開發手冊3.0 官方用戶交流:iApp開發交流(1) 239547050iApp開發交流(2) 10...
    葉染柒丶閱讀 5,264評論 0 7
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,702評論 25 708
  • 上一次哈哈跟大家整理了兩句快速學五十音圖的口訣。不知道大家有沒有看哈。其實五十音的話是一個非常有規律的一個圖表,跟...
    dc3c12c58779閱讀 932評論 0 0
  • 被突如其來的好牌沖昏了頭腦,沒有細致思考,片面認為好牌在手抖都不抖,老子最大,天不怕地不怕,結果一招不慎,滿盤皆輸...
    榮海田閱讀 172評論 0 0