欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Angular.js4.x中表單Template-DrivenForms詳解

Angular 4.x 中有兩種表單:

創(chuàng)新互聯(lián)主要從事網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)云夢(mèng),十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):18982081108

  • Template-Driven Forms - 模板驅(qū)動(dòng)式表單 (類(lèi)似于 Angular 1.x 中的表單 )
  • Reactive Forms - 響應(yīng)式表單

本文主要介紹 Template-Driven Forms (模板驅(qū)動(dòng)式表單) ,將涉及 ngForm、ngModel、ngModelGroup、表單提交事件、表單驗(yàn)證和異常信息輸出等內(nèi)容。

Contents

  • ngModule and template-driven forms
  • Binding ngForm and ngModel
  • ngModel,[ngModel] and [(ngModel)]
  • ngModels and ngModelGroup
  • Template-driven submit
  • Template-driven error validation

Form base and interface

Form base

<form novalidate>
 <label>
 <span>Full name</span>
 <input
 type="text"
 name="name"
 placeholder="Your full name">
 </label>
 <div>
 <label>
 <span>Email address</span>
 <input
 type="email"
 name="email"
 placeholder="Your email address">
 </label>
 <label>
 <span>Confirm address</span>
 <input
 type="email"
 name="confirm"
 placeholder="Confirm your email address">
 </label>
 </div>
 <button type="submit">Sign up</button>
</form>

接下來(lái)我們要實(shí)現(xiàn)的功能如下:

  • 綁定 name、email、confirm 輸入框的值
  • 為所有輸入框添加表單驗(yàn)證功能
  • 顯示驗(yàn)證異常信息
  • 表單驗(yàn)證失敗時(shí),不允許進(jìn)行表單提交
  • 表單提交功能

User interface

// signup.interface.ts
export interface User {
 name: string;
 account: {
 email: string;
 confirm: string;
 }
}

ngModule and template-driven forms

在我們繼續(xù)深入介紹 template-driven 表單前,我們必須在 @NgModule 中導(dǎo)入 @angular/forms 庫(kù)中的 FormModule:

import { FormsModule } from '@angular/forms';

@NgModule({
 imports: [
 ...,
 FormsModule
 ],
 declarations: [...],
 bootstrap: [...]
})
export class AppModule {}

友情提示:若使用 template-driven 表單,則導(dǎo)入 FormsModule;若使用 reactive forms,則導(dǎo)入 ReactiveFormsModule。

Template-driven approach

使用模板驅(qū)動(dòng)的表單,我們基本上可以將組件類(lèi)留空,直到我們需要讀取/寫(xiě)入值 (例如提交和設(shè)置初始值)。我們將基于上面的定義的基礎(chǔ)表單,創(chuàng)建 SignupFormComponent :

signup-form.component.ts

import { Component } from '@angular/core';

@Component({
 selector: 'signup-form',
 template: `
 <form novalidate>...</form>
 `
})
export class SignupFormComponent {
 constructor() {}
}

這是一個(gè)很基礎(chǔ)的組件,接下來(lái)我們導(dǎo)入之前定義的 User 接口,具體如下:

import { User } from './signup.interface';

@Component({...})
export class SignupFormComponent {
 public user: User = {
 name: '',
 account: {
 email: '',
 confirm: ''
 }
 };
}

初始化 SignupFormComponent 組件類(lèi)中的用戶(hù)模型后,我們開(kāi)始實(shí)現(xiàn)第一個(gè)功能點(diǎn):即綁定 name、email、confirm 輸入框的值。

Binding ngForm and ngModel

我們從 ngForm 開(kāi)始,更新后的模板如下:

<form novalidate #f="ngForm">
 <label>
 <span>Full name</span>
 <input type="text" placeholder="Your full name">
 </label>
</form>

上面代碼中,我們把 ngForm 的值賦值給 #f 變量,通過(guò)該變量我們可以方便的獲取表單的值。

友情提示:#f 變量的值,是 ngForm 指令的導(dǎo)出對(duì)象。

@Directive({
 selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]',
 providers: [formDirectiveProvider],
 host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
 outputs: ['ngSubmit'],
 exportAs: 'ngForm'
})
export class NgForm extends ControlContainer implements Form {}

在模板中,我們可以通過(guò)以下方式查看表單的值:

{{ f.value | json }} // {}

上面示例 f.value 輸出 {},因?yàn)榇藭r(shí)我們表單中還未綁定任何值。在 Angular 1.x 中我們可以使用 ng-model 指令進(jìn)行表單數(shù)據(jù)的雙向綁定,接下來(lái)我們來(lái)看一下 Angular 4.x 中怎么實(shí)現(xiàn)數(shù)據(jù)綁定。

ngModel,[ngModel] and [(ngModel)]

在 Angular 4.x 中 ngModel 有三種不同的語(yǔ)法:

1、ngModel - 直接使用 ngModel 指令,沒(méi)有使用綁定或關(guān)聯(lián)任何值。

此時(shí),ngModel 將自動(dòng)關(guān)聯(lián)表單控件的 name 屬性,并使用該值作為 ngForm 對(duì)象的屬性名。

<form novalidate #f="ngForm">
 ...
 <input
 type="text"
 placeholder="Your full name"
 name="name"
 ngModel>
 ...
</form>

友情提示:上面示例中,如果 input 輸入框若未設(shè)置 name 屬性,應(yīng)用將會(huì)拋出異常。ngModel 指令基于輸入框的 name 屬性,進(jìn)行綁定。

運(yùn)行以上代碼,f.value 的輸入值如下:

{{ f.value | json }} // { name: '' }

非常好,我們已經(jīng)綁定了 name 輸入框的值。但我們應(yīng)該怎么為輸入框設(shè)置初始值?

2、[ngModel] = one-way binding syntax (單向綁定語(yǔ)法)

為了設(shè)置輸入框初始值,我們先要更新一下 SignupFormComponent 組件類(lèi)的用戶(hù)模型:

...
user: User = {
 name: 'Semlinker',
 account: {
 email: '',
 confirm: ''
 }
};
...

更新完用戶(hù)模型,我們需要同步更新組件模板,具體如下:

<form #f="ngForm">
 ...
 <input
 type="text"
 placeholder="Your full name"
 name="name"
 [ngModel]="user.name">
 ...
</form>

代碼重新運(yùn)行后,f.value 的輸出如下:

{{ f.value | json }} // { name: 'Semlinker' }

從上面示例可以看出,使用 [ngModel] 允許我們通過(guò) this.user.name 設(shè)置 name 輸入框的初始值,而且該值會(huì)自動(dòng)綁定到 f.value 對(duì)象上。

友情提示: [ngModel] 是單向綁定,當(dāng)表單中 name 輸入框的值改變時(shí),不會(huì)同步更新 this.user.name

如果想在 name 輸入框值變化時(shí),自動(dòng)同步更新 this.user.name 的值,我們需要使用雙向綁定。

3、[(ngModel)] = two-way binding syntax (雙向綁定),具體示例如下:

<form #f="ngForm">
 ...
 <input
 type="text"
 placeholder="Your full name"
 name="name"
 [(ngModel)]="user.name">
 ...
</form>

上面示例成功運(yùn)行后,我們可以在模板中新增以下代碼,然后觀察 user 模型的值:

{{ user | json }} // { name: 'Semlinker' }

需要注意的是:以下兩種方式是等價(jià)的:

<input [(ngModel)]="user.name">
<input [ngModel]="user.name" (ngModelChange)="user.name = $event">

其中 [(ngModel)] 是簡(jiǎn)寫(xiě)的語(yǔ)法糖。

ngModels and ngModelGroup

我們已經(jīng)介紹了 ngForm 和 ngModel 的基礎(chǔ)用法,現(xiàn)在我們來(lái)完善剩下的內(nèi)容。SignupFormComponent 組件類(lèi)的用戶(hù)模型中,包含了一個(gè)嵌套屬性 account ,account 對(duì)象中包含 email 和 confirm 屬性,分為表示郵件地址和重復(fù)確認(rèn)的郵件地址。針對(duì)這種場(chǎng)景,Angular 4.x 為我們提供了 ngModelGroup 指令,具體示例如下:

<form novalidate #f="ngForm">
 <label>
 <span>Full name</span>
 <input
 type="text"
 placeholder="Your full name"
 name="name"
 ngModel>
 </label>
 <div ngModelGroup="account">
 <label>
 <span>Email address</span>
 <input
 type="email"
 placeholder="Your email address"
 name="email"
 ngModel>
 </label>
 <label>
 <span>Confirm address</span>
 <input
 type="email"
 placeholder="Confirm your email address"
 name="confirm"
 ngModel>
 </label>
 </div>
 <button type="submit">Sign up</button>
</form>

使用 ngModelGroup 指令后,我們的 DOM 結(jié)構(gòu)將更加合理:

ngForm -> '#f'
 ngModel -> 'name'
 ngModelGroup -> 'account'
   -> ngModel -> 'email'
   -> ngModel -> 'confirm'

以上代碼成功運(yùn)行后,瀏覽器中頁(yè)面顯示的結(jié)果:

// { name: 'Semlinker', account: { email: '', confirm: '' } }
{{ f.value | json }}

此時(shí)我們已經(jīng)完成了表單數(shù)據(jù)綁定,接下來(lái)我們來(lái)為表單增加提交邏輯。

Template-driven submit

Angular 表單中提供了 ngSubmit 輸出屬性,用于監(jiān)聽(tīng)表單的提交事件:

<form novalidate (ngSubmit)="onSubmit(f)" #f="ngForm">
 ...
</form>

當(dāng)用戶(hù)提交表單時(shí),我們將會(huì)把 f 作為參數(shù),調(diào)用 ngSubmit 關(guān)聯(lián)的 onSubmit() 方法。onSubmit() 方法的具體實(shí)現(xiàn)如下:

export class SignupFormComponent {
 user: User = {...};
 onSubmit({ value, valid }: { value: User, valid: boolean }) {
 console.log(value, valid);
 }
}

上面代碼中,我們使用 Object destructuring (對(duì)象解構(gòu)) 的方式,從#f 引用對(duì)象中獲取 value 和 valid 屬性的值。其中 value 的值,就是 f.value 的值。表單的數(shù)據(jù)綁定方式和提交邏輯已經(jīng)介紹完了,是該介紹表單實(shí)際應(yīng)用中,一個(gè)重要的環(huán)節(jié) — 表單驗(yàn)證。

Template-driven error validation

在為表單項(xiàng)添加驗(yàn)證規(guī)則前,我們先來(lái)更新一下 SignupFormComponent 組件中的 Sign up 按鈕,確保在表單驗(yàn)證不通過(guò)時(shí),不允許用戶(hù)執(zhí)行表單提交操作。

更新后的代碼如下:

<form novalidate (ngSubmit)="onSubmit(f)" #f="ngForm">
 ...
 <button type="submit" [disabled]="f.invalid">Sign up</button>
</form>

以上代碼我們通過(guò) f.invalid 獲取表單當(dāng)前的驗(yàn)證狀態(tài) (驗(yàn)證不通過(guò)時(shí)該值為true),來(lái)控制按鈕的 disabled 屬性。

接下來(lái)開(kāi)始進(jìn)入正題,為表單添加驗(yàn)證規(guī)則:

<form novalidate #f="ngForm">
 <label>
 ...
 <input
 ...
 ngModel
 required>
 </label>
 <div ngModelGroup="account">
 <label>
 ...
 <input
 ...
 name="email"
 ngModel
 required>
 </label>
 <label>
 ...
 <input
 ...
 name="confirm"
 ngModel
 required>
 </label>
 </div>
 <button type="submit">Sign up</button>
</form>

上面代碼中,我們?yōu)槊總€(gè) input 表單控件,添加了 required (必填項(xiàng)) 的驗(yàn)證規(guī)則。一切都那么簡(jiǎn)單,剩下的問(wèn)題就是如何獲取驗(yàn)證失敗的異常消息。

皇上,您還記得當(dāng)年大明湖畔的夏雨荷嗎? — No,No,No !我只記得安谷拉 (angular) 湖畔的美女 (f)。

#f 引用對(duì)象中有一個(gè) controls 屬性,通過(guò)該屬性,我們就可以獲取表單控件的驗(yàn)證信息,下面示例演示了如何獲取 name 表單控件驗(yàn)證的異常信息:

<form novalidate #f="ngForm">
 {{ f.controls.name?.errors | json }}
</form>

f.controls.name?.errors 的值是 null 或 undefined 時(shí),表示驗(yàn)證成功。

友情提示: ?.prop 稱(chēng)為安全導(dǎo)航操作符,用于告訴 Angular prop 的值可能不存在。

接下來(lái)為我們的 name 表單控件,添加顯示異常信息的代碼:

<div *ngIf="f.controls.name?.required" class="error">
 Name is required
</div>

雖然我們已經(jīng)可以獲取某個(gè)表單項(xiàng)的驗(yàn)證信息,但有沒(méi)有覺(jué)得使用 f.controls.name?.errors 這種方式,太麻煩了。那么有沒(méi)有更簡(jiǎn)單的方式呢?我的答案是 - Yes !廢話(huà)不多說(shuō),馬上看示例:

<label>
 ...
 <input
 ...
 #userName="ngModel"
 required>
</label>
<div *ngIf="userName.errors?.required" class="error">
 Name is required
</div>

(備注:此處一定要使用 #userName="ngModel")

以上代碼成功運(yùn)行后,我們?cè)跒g覽器中看到了異常信息,為了避免一開(kāi)始就顯示異常信息,我們可以更新一下 *ngIf 表達(dá)式的驗(yàn)證邏輯:

<div *ngIf="userName.errors?.required && userName.touched" 
 class="error">
 Name is required
</div>

除了使用 required 驗(yàn)證規(guī)則之外,我們還可以使用 minlength (最小長(zhǎng)度)、maxlength (最大長(zhǎng)度) 等驗(yàn)證規(guī)則,下面我們繼續(xù)來(lái)完善 SignupFormComponent 組件的功能,即為其它的表單控件添加顯示異常信息的功能:

<!-- name -->
<div *ngIf="userName.errors?.required && userName.touched" 
 class="error">
 Name is required
</div>
<div *ngIf="userName.errors?.minlength && userName.touched" 
 class="error">
 Minimum of 2 characters
</div>

<!-- account: { email, confirm } -->
<div *ngIf="userEmail.errors?.required && userEmail.touched" 
 class="error">
 Email is required
</div>
<div *ngIf="userConfirm.errors?.required && userConfirm.touched" 
 class="error">
 Confirming email is required
</div>

我們通過(guò)使用模板變量的方式,為 account 表單組添加了顯示驗(yàn)證異常信息的功能。但有沒(méi)有其它更好的方式呢?有沒(méi)有辦法去掉 userEmail 和 userConfirm 引用對(duì)象呢?答案是肯定的,具體示例如下:

<div ngModelGroup="account" #userAccount="ngModelGroup">
 <label>
 <span>Email address</span>
 <input
 type="email"
 placeholder="Your email address"
 name="email"
 ngModel
 required>
 </label>
 <label>
 <span>Confirm address</span>
 <input
 type="email"
 placeholder="Confirm your email address"
 name="confirm"
 ngModel
 required>
 </label>
 <div *ngIf="userAccount.invalid && userAccount.touched" class="error">
 Both emails are required
 </div>
</div>

(備注:記得移除模板上的 #userEmail 和 #userConfirm 引用哈)

我有話(huà)說(shuō)

表單控件的狀態(tài)除了 touched 外,還包含其它幾種狀態(tài)?

表單控件有以下 6 種狀態(tài),我們可以通過(guò) #userName="ngModel" 方式獲取對(duì)應(yīng)的狀態(tài)值。

具體狀態(tài)如下:

  • valid - 表單控件有效
  • invalid - 表單控件無(wú)效
  • pristine - 表單控件值未改變
  • dirty - 表單控件值已改變
  • touched - 表單控件已被訪(fǎng)問(wèn)過(guò)
  • untouched - 表單控件未被訪(fǎng)問(wèn)過(guò)

表單控件上 #userName#userName="ngModel" 這兩種方式有什么區(qū)別?

  • #userName - 指向 input 表單控件
  • #userName="ngModel" - 指向 NgModel 實(shí)例

ngModel 指令

// angular2/packages/forms/src/directives/ng_model.ts 片段
@Directive({
 selector: '[ngModel]:not([formControlName]):not([formControl])',
 providers: [formControlBinding],
 exportAs: 'ngModel' // // 導(dǎo)出指令實(shí)例,使得可以在模板中調(diào)用
})
export class NgModel extends NgControl implements OnChanges, OnDestroy {
}

NgControl 抽象類(lèi)

// angular2/packages/forms/src/directives/ng_control.ts 片段
export abstract class NgControl extends AbstractControlDirective {
 /** @internal */
 _parent: ControlContainer = null;
 name: string = null;
 valueAccessor: ControlValueAccessor = null;
 ...
 abstract viewToModelUpdate(newValue: any): void;
}

AbstractControlDirective 抽象類(lèi)

// angular2/packages/forms/src/directives/abstract_control_directive.ts 片段
export abstract class AbstractControlDirective {
 get valid(): boolean { return this.control ? this.control.valid : null; }

 get invalid(): boolean { return this.control ? this.control.invalid : null; }

 get errors(): ValidationErrors | null { return this.control ? 
 this.control.errors : null; }

 get pristine(): boolean { return this.control ? this.control.pristine : null; }

 get dirty(): boolean { return this.control ? this.control.dirty : null; }

 get touched(): boolean { return this.control ? this.control.touched : null; }

 get untouched(): boolean { return this.control ? this.control.untouched : null; }

 get valueChanges(): Observable<any> { return this.control ? 
 this.control.valueChanges : null; }

 hasError(errorCode: string, path: string[] = null): boolean {
 return this.control ? this.control.hasError(errorCode, path) : false;
 }

 getError(errorCode: string, path: string[] = null): any {
 return this.control ? this.control.getError(errorCode, path) : null;
 }
}

ngModelGroup 有什么作用?

ngModelGroup 指令是 Angular 提供的另一特殊指令,可以對(duì)表單輸入內(nèi)容進(jìn)行分組,方便我們?cè)谡Z(yǔ)義上區(qū)分不同性質(zhì)的輸入。例如聯(lián)系人的信息包括姓名及住址,現(xiàn)在需對(duì)姓名和住址進(jìn)行精細(xì)化信息收集,姓名可精細(xì)化成姓和名字,地址可精細(xì)化成城市、區(qū)、街等。此時(shí)就可以將姓名及住址進(jìn)行分組收集,具體如下:

<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 ngModelGroup="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>

上述例子分別對(duì)聯(lián)系人的姓名和住址進(jìn)行分組, ngModelGroup 將姓和名字的表單內(nèi)容進(jìn)行包裹組成姓名分組,將城市、區(qū)和街道的表單內(nèi)容進(jìn)行包裹組成住址分組。此時(shí)concatForm.value值為:

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

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。

當(dāng)前文章:Angular.js4.x中表單Template-DrivenForms詳解
網(wǎng)頁(yè)路徑:http://chinadenli.net/article22/gpdecc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、手機(jī)網(wǎng)站建設(shè)、云服務(wù)器、響應(yīng)式網(wǎng)站、電子商務(wù)、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)