ng2表單

angular提供了模板驅(qū)動(dòng)和模型驅(qū)動(dòng)兩種方式來(lái)構(gòu)建表單。模板驅(qū)動(dòng)模式使用模板表單內(nèi)置指令、內(nèi)置校驗(yàn)的方式來(lái)構(gòu)建表單;模型驅(qū)動(dòng)模式采用自定義表單、自定義校驗(yàn)的方式來(lái)構(gòu)建表單。

表單指令

NgForm指令

NgForm指令是表單的控制中心,負(fù)責(zé)處理表單內(nèi)的頁(yè)面邏輯,為普通的表單元素?cái)U(kuò)充了許多額外的特性,所有的表單指令都需要在NgForm指令內(nèi)部才能正常運(yùn)行。
首先要在根模塊中添加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  //導(dǎo)入FormsModule
    ],
    declarations:[
        AppComponent,
        FormComponent
    ],
    bootstrap:[AppComponent]
})
export class AppModule {}

可以不用在模板中顯式的使用NgForm指令,因?yàn)樘砑恿?code>FormsModule模塊后,angular模板在編譯解析時(shí),遇到<form>標(biāo)簽會(huì)自動(dòng)創(chuàng)建一個(gè)NgForm指令并且將其添加到該<form>標(biāo)簽上。

NgModel指令

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

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

在控件中使用NgModel屬性綁定,必須給該控件添加name屬性,否則會(huì)報(bào)錯(cuò)。因?yàn)?code>NgForm指令會(huì)為表單建立一個(gè)控件對(duì)象FormControl的集合,以此來(lái)作為表單控件的容器??丶?code>NgModel屬性綁定會(huì)以name作為唯一標(biāo)識(shí)符來(lái)注冊(cè)并生成一個(gè)FormControl,將其加入到FormControl的集合中。

常用的表單控件:

單選框:?jiǎn)芜x框控件實(shí)現(xiàn)雙向數(shù)據(jù)綁定,同一組單選框控件的所有[(ngModel)]屬性都必須綁定同一個(gè)模型數(shù)據(jù),且name屬性名也必須相同。

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

當(dāng)單擊選項(xiàng)為“女”的單選框,curContact.sex會(huì)被賦值為female,若單擊“男”單選框,則所對(duì)應(yīng)的值為male
復(fù)選框:復(fù)選框控件用來(lái)表示該表單復(fù)選框是否被選中,其中[(ngModel)]屬性綁定的是一個(gè)布爾值。

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

如果復(fù)選框被選中,則curContact.lock的值為true,否則為false。
單選下拉框:?jiǎn)芜x下拉框控件的雙向數(shù)據(jù)綁定需結(jié)合option元素綁定的值來(lái)實(shí)現(xiàn)。option選項(xiàng)的元素屬性的綁定目標(biāo)有兩種,分別為valuengValue。當(dāng)在option元素中使用value綁定數(shù)據(jù)時(shí),其返回值類型是基本數(shù)據(jù)類型;當(dāng)使用ngValue綁定數(shù)據(jù)時(shí),其返回值類型是對(duì)象數(shù)據(jù)類型。

//定義下拉框所需所需數(shù)據(jù)
export class FormComponent {
    interests:any[]=[
        {value:'reading',display:'閱讀'},
        {value:'traveling',display:'旅游'},
        {value:'sport',display:'運(yùn)動(dòng)'}
    ];
}

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

例子中,使用[value]來(lái)綁定下拉選項(xiàng)的value屬性值,如果選中下拉選項(xiàng)框中的“旅游”項(xiàng),那么curContact.interestValue的值將變?yōu)?code>traveling。
單選框被選中后也可以返回對(duì)象類型的數(shù)據(jù)。

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

當(dāng)選中某個(gè)項(xiàng)目后,該下拉框最終返回一個(gè)Object類型的對(duì)象數(shù)據(jù)。如選中“旅游”項(xiàng),則curContact.interestObj的值為{value:'traveling',display:'旅游'}
多選下拉框:實(shí)現(xiàn)了下拉選擇多個(gè)選項(xiàng)的功能,返回的數(shù)據(jù)是一個(gè)由所有被選項(xiàng)數(shù)據(jù)組成的數(shù)組。

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

多選下拉框使用[value]來(lái)綁定下拉選項(xiàng)的value屬性值,如果在多選下拉框中選中“旅游”和“運(yùn)動(dòng)”兩項(xiàng),則curContact.interestMul返回值為["traveling","sport"]
多選下拉框還可以使用[ngValue]來(lái)綁定下拉選項(xiàng)的value屬性值,如果在多選下拉框中選中“旅游”和“運(yùn)動(dòng)”兩項(xiàng),那么curContact.interestMul返回的數(shù)組對(duì)象為[{value:'traveling',display:'旅游'},{value:'sport',display:'運(yùn)動(dòng)'}]。

模板局部變量

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

DOM元素局部變量

若在標(biāo)簽元素中定義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會(huì)自動(dòng)把局部變量設(shè)置為對(duì)當(dāng)前DOM元素對(duì)象的引用,如上面的局部變量contactName引用的是document.getElementById("contactName")對(duì)象。在模板中定義局部變量后,可以直接在模板的其他元素中使用該元素的DOM屬性,如contactName.valuetelNum.value

表單指令局部變量

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

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指令實(shí)例對(duì)象的引用,可以在模板中讀取NgForm實(shí)例對(duì)象的屬性值,如追蹤表單的valid屬性狀態(tài)。當(dāng)被包含的所有控件都有效時(shí),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是對(duì)NgModel指令實(shí)例對(duì)象的引用,可以在模板中讀取NgModel實(shí)例對(duì)象的屬性值,如通過(guò)contactName.valid可追蹤控件狀態(tài)、表單校驗(yàn)不通過(guò)時(shí)提示錯(cuò)誤信息。

表單狀態(tài)

表單NgFormNgNodel指令都可以用于追蹤表單狀態(tài)來(lái)實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)。表單NgFormNgModel指令都有五個(gè)表示狀態(tài)的屬性,屬性值都為布爾類型,并都可通過(guò)對(duì)應(yīng)的局部變量獲取。NgForm追蹤的是整個(gè)表單控件的狀態(tài),NgModel追蹤的是其所在表單控件的狀態(tài)。

表單狀態(tài)屬性語(yǔ)義表

NgModelGroup指令

NgModelGroup指令可以對(duì)表單輸入內(nèi)容進(jìn)行分組,方便我們?cè)谡Z(yǔ)義上區(qū)分不同類型的輸入。

<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>區(qū):</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實(shí)例對(duì)象的valid屬性可以單獨(dú)校驗(yàn)其所在分組控件的輸入是否有效。如上例中只有當(dāng)curContact.firstname、curContact.lastname輸入都有效時(shí),局部變量nameGroup.valid才會(huì)變成true,否則為false。

ngSubmit事件

ngSubmit事件可以響應(yīng)表單里類型為submit的按鈕操作,并負(fù)責(zé)控制表單的提交流程。當(dāng)按鈕被單機(jī)后,會(huì)觸發(fā)表單的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){
        //處理表單數(shù)據(jù)并提交
    }
}

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

自定義表單樣式

NgModel指令不僅能追蹤表單控件的狀態(tài),還會(huì)根據(jù)表單控件的狀態(tài)使用對(duì)應(yīng)的CSS狀態(tài)類來(lái)更新表單控件的類名。表單控件包括6個(gè)CSS狀態(tài)類。

控件CSS狀態(tài)類名

表單控件的CSS類名會(huì)根據(jù)表單控件狀態(tài)變化而變化。

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

還可結(jié)合控件的狀態(tài)屬性valid、pristine、dirty、touched、untouched等來(lái)添加有用的消息提示,以此來(lái)對(duì)用戶進(jìn)行有效的引導(dǎo)。

<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">
        用戶名長(zhǎng)度3-10個(gè)字符
    </p>
</div>

表單校驗(yàn)

表單內(nèi)置校驗(yàn)

angular支持的表單內(nèi)置校驗(yàn)包括:

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

可以在<form>標(biāo)簽中添加novalidate屬性來(lái)屏蔽HTML的攔截校驗(yàn)。

表單自定義校驗(yàn)

創(chuàng)建自定義校驗(yàn)

下面定義一個(gè)用戶名的校驗(yàn)器,校驗(yàn)規(guī)則為:用戶名必須是郵箱、手機(jī)號(hào)碼的格式。

//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:'用戶名必須是手機(jī)號(hào)或郵箱帳號(hào)'
        }
    }
}

自定義校驗(yàn)函數(shù)傳入的參數(shù)是FormControl類,通過(guò)對(duì)FormControlvalue值進(jìn)行校驗(yàn)處理,返回校驗(yàn)結(jié)果。

使用自定義校驗(yàn)

使用模型驅(qū)動(dòng)方式構(gòu)建表單,需在表單組件所在的模塊代碼中導(dǎo)入ReactiveFormsModule,并在模塊的@NgModule元數(shù)據(jù)imports數(shù)組中加入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 {}

導(dǎo)入ReactiveFormsModule后,可在表單組件FormComponent中使用模型驅(qū)動(dòng)方式構(gòu)建表單。

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)
    });
}

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

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

如果需要在一個(gè)表單中添加多個(gè)校驗(yàn)器,可以在校驗(yàn)配置參數(shù)中使用數(shù)組,數(shù)組元素為對(duì)應(yīng)的校驗(yàn)方法。

customForm=new FormGroup({
    customName:new FormControl('',[Validators.minLength(4),ValidateUserName])
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容