亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Angular.js 4.x中表單Template-Driven Forms詳解

2019-11-19 16:44:10
字體:
來源:轉載
供稿:網友

Angular 4.x 中有兩種表單:

  • Template-Driven Forms - 模板驅動式表單 (類似于 Angular 1.x 中的表單 )
  • Reactive Forms - 響應式表單

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

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>

接下來我們要實現的功能如下:

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

User interface

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

ngModule and template-driven forms

在我們繼續深入介紹 template-driven 表單前,我們必須在 @NgModule 中導入 @angular/forms 庫中的 FormModule:

import { FormsModule } from '@angular/forms';@NgModule({ imports: [ ..., FormsModule ], declarations: [...], bootstrap: [...]})export class AppModule {}

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

Template-driven approach

使用模板驅動的表單,我們基本上可以將組件類留空,直到我們需要讀取/寫入值 (例如提交和設置初始值)。我們將基于上面的定義的基礎表單,創建 SignupFormComponent :

signup-form.component.ts

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

這是一個很基礎的組件,接下來我們導入之前定義的 User 接口,具體如下:

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

初始化 SignupFormComponent 組件類中的用戶模型后,我們開始實現第一個功能點:即綁定 name、email、confirm 輸入框的值。

Binding ngForm and ngModel

我們從 ngForm 開始,更新后的模板如下:

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

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

友情提示: #f 變量的值,是 ngForm 指令的導出對象。

@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 {}

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

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

上面示例 f.value 輸出 {},因為此時我們表單中還未綁定任何值。在 Angular 1.x 中我們可以使用 ng-model 指令進行表單數據的雙向綁定,接下來我們來看一下 Angular 4.x 中怎么實現數據綁定。

ngModel,[ngModel] and [(ngModel)]

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

1、ngModel - 直接使用 ngModel 指令,沒有使用綁定或關聯任何值。

此時,ngModel 將自動關聯表單控件的 name 屬性,并使用該值作為 ngForm 對象的屬性名。

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

友情提示:上面示例中,如果 input 輸入框若未設置 name 屬性,應用將會拋出異常。ngModel 指令基于輸入框的 name 屬性,進行綁定。

運行以上代碼,f.value 的輸入值如下:

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

非常好,我們已經綁定了 name 輸入框的值。但我們應該怎么為輸入框設置初始值?

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

為了設置輸入框初始值,我們先要更新一下 SignupFormComponent 組件類的用戶模型:

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

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

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

代碼重新運行后,f.value 的輸出如下:

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

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

友情提示: [ngModel] 是單向綁定,當表單中 name 輸入框的值改變時,不會同步更新 this.user.name

如果想在 name 輸入框值變化時,自動同步更新 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>

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

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

需要注意的是:以下兩種方式是等價的:

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

其中 [(ngModel)] 是簡寫的語法糖。

ngModels and ngModelGroup

我們已經介紹了 ngForm 和 ngModel 的基礎用法,現在我們來完善剩下的內容。SignupFormComponent 組件類的用戶模型中,包含了一個嵌套屬性 account ,account 對象中包含 email 和 confirm 屬性,分為表示郵件地址和重復確認的郵件地址。針對這種場景,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 結構將更加合理:

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

以上代碼成功運行后,瀏覽器中頁面顯示的結果:

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

此時我們已經完成了表單數據綁定,接下來我們來為表單增加提交邏輯。

Template-driven submit

Angular 表單中提供了 ngSubmit 輸出屬性,用于監聽表單的提交事件:

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

當用戶提交表單時,我們將會把 f 作為參數,調用 ngSubmit 關聯的 onSubmit() 方法。onSubmit() 方法的具體實現如下:

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

上面代碼中,我們使用 Object destructuring (對象解構) 的方式,從#f 引用對象中獲取 value 和 valid 屬性的值。其中 value 的值,就是 f.value 的值。表單的數據綁定方式和提交邏輯已經介紹完了,是該介紹表單實際應用中,一個重要的環節 ― 表單驗證。

Template-driven error validation

在為表單項添加驗證規則前,我們先來更新一下 SignupFormComponent 組件中的 Sign up 按鈕,確保在表單驗證不通過時,不允許用戶執行表單提交操作。

更新后的代碼如下:

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

以上代碼我們通過 f.invalid 獲取表單當前的驗證狀態 (驗證不通過時該值為true),來控制按鈕的 disabled 屬性。

接下來開始進入正題,為表單添加驗證規則:

<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>

上面代碼中,我們為每個 input 表單控件,添加了 required (必填項) 的驗證規則。一切都那么簡單,剩下的問題就是如何獲取驗證失敗的異常消息。

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

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

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

f.controls.name?.errors 的值是 null 或 undefined 時,表示驗證成功。

友情提示: ?.prop 稱為安全導航操作符,用于告訴 Angular prop 的值可能不存在。

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

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

雖然我們已經可以獲取某個表單項的驗證信息,但有沒有覺得使用 f.controls.name?.errors 這種方式,太麻煩了。那么有沒有更簡單的方式呢?我的答案是 - Yes !廢話不多說,馬上看示例:

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

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

以上代碼成功運行后,我們在瀏覽器中看到了異常信息,為了避免一開始就顯示異常信息,我們可以更新一下 *ngIf 表達式的驗證邏輯:

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

除了使用 required 驗證規則之外,我們還可以使用 minlength (最小長度)、maxlength (最大長度) 等驗證規則,下面我們繼續來完善 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>

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

<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 引用哈)

我有話說

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

表單控件有以下 6 種狀態,我們可以通過 #userName="ngModel" 方式獲取對應的狀態值。

具體狀態如下:

  • valid - 表單控件有效
  • invalid - 表單控件無效
  • pristine - 表單控件值未改變
  • dirty - 表單控件值已改變
  • touched - 表單控件已被訪問過
  • untouched - 表單控件未被訪問過

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

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

ngModel 指令

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

NgControl 抽象類

// 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 抽象類

// 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 提供的另一特殊指令,可以對表單輸入內容進行分組,方便我們在語義上區分不同性質的輸入。例如聯系人的信息包括姓名及住址,現在需對姓名和住址進行精細化信息收集,姓名可精細化成姓和名字,地址可精細化成城市、區、街等。此時就可以將姓名及住址進行分組收集,具體如下:

<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>區:</label> <input type="text" name="zip" [(ngModel)]="curContact.zip" required>  <label>城市:</label> <input type="text" name="city" [(ngModel)]="curContact.city" required> </fieldset></form>

上述例子分別對聯系人的姓名和住址進行分組, ngModelGroup 將姓和名字的表單內容進行包裹組成姓名分組,將城市、區和街道的表單內容進行包裹組成住址分組。此時concatForm.value值為:

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本精品久久电影| 精品久久久久久中文字幕一区奶水| 久久综合国产精品台湾中文娱乐网| 国产视频一区在线| 欧美日韩一区二区免费在线观看| 亚洲男人天天操| 欧美一级成年大片在线观看| 亚洲japanese制服美女| 最好看的2019年中文视频| 精品福利视频导航| 中文字幕av日韩| 欧美xxxx18国产| 91精品美女在线| 久久91亚洲精品中文字幕| 亚洲欧美日韩在线高清直播| 2019中文字幕免费视频| 日本一本a高清免费不卡| 另类视频在线观看| 91网站在线免费观看| 欧美激情一区二区三区高清视频| 疯狂欧美牲乱大交777| 亚洲国产97在线精品一区| 国产日韩精品视频| 国产成人精品一区二区在线| 一本色道久久综合狠狠躁篇的优点| 日韩电影中文字幕在线| 国产精品永久免费| 自拍偷拍亚洲在线| 欧美精品激情blacked18| 精品自在线视频| 国产一区二区在线播放| 成人黄色在线观看| 日韩在线不卡视频| 国产精品ⅴa在线观看h| 久久久午夜视频| 国产精品老牛影院在线观看| 国产亚洲日本欧美韩国| 这里只有精品在线观看| 91人人爽人人爽人人精88v| 国产精品h在线观看| 欧美巨猛xxxx猛交黑人97人| 国产精品一区二区女厕厕| 亚洲午夜久久久久久久| 国产精品激情av在线播放| 伊人av综合网| 日韩美女毛茸茸| 欧美高清视频免费观看| 日本精品一区二区三区在线播放视频| 欧美激情a∨在线视频播放| 国产极品精品在线观看| 国产精品爱啪在线线免费观看| 久热99视频在线观看| 亚洲精品自拍第一页| 青青草国产精品一区二区| 成人av在线天堂| 日韩在线中文字幕| 欧美国产日韩一区二区在线观看| 最近2019年好看中文字幕视频| 亚洲娇小xxxx欧美娇小| 日韩精品一二三四区| 久久国产精品免费视频| 91沈先生在线观看| 91在线无精精品一区二区| 亚洲国产精品一区二区久| 久久精品视频亚洲| 国内免费精品永久在线视频| 久久视频免费观看| 亚洲区一区二区| 97视频免费看| 中日韩午夜理伦电影免费| 日韩国产中文字幕| 91精品久久久久久| 中文国产亚洲喷潮| 日韩成人在线网站| 精品欧美aⅴ在线网站| 日韩av片电影专区| 国产精品视频xxx| 国产一区二区三区在线视频| 国产亚洲精品一区二555| 国内精品400部情侣激情| 91精品国产自产在线观看永久| 91成人性视频| 久热国产精品视频| 奇米影视亚洲狠狠色| 精品成人国产在线观看男人呻吟| 欧美成人在线影院| 亚洲毛片在线观看.| 国产精品久久91| 亚洲sss综合天堂久久| 欧美成人久久久| 久久国产加勒比精品无码| 7m精品福利视频导航| 欧美理论电影在线观看| 亚洲免费一在线| 日韩精品视频观看| 欧美片一区二区三区| 欧美一区二区色| 日韩精品在线私人| 欧美性xxxxx极品娇小| 精品成人国产在线观看男人呻吟| 亚洲精品视频在线观看视频| 欧美人与性动交| 亚洲www视频| 亚洲美女又黄又爽在线观看| 国产日韩精品电影| 一本大道久久加勒比香蕉| 亚洲精品中文字幕有码专区| 97在线观看视频| 日韩电影在线观看免费| 日韩成人网免费视频| 丁香五六月婷婷久久激情| 亚洲韩国欧洲国产日产av| 欧美日韩激情视频| 国产欧美日韩91| 日韩女在线观看| 亚洲国产精品va在线看黑人动漫| 国产在线观看不卡| 国产精品美女久久久久久免费| 亚洲精品国产suv| 国产精品黄页免费高清在线观看| 亚洲激情在线观看视频免费| 97色在线视频观看| 麻豆国产va免费精品高清在线| 中文日韩在线观看| 8050国产精品久久久久久| 26uuu另类亚洲欧美日本老年| 91亚洲国产成人久久精品网站| 久久99热精品这里久久精品| 国产91亚洲精品| 国产精品久久久久久婷婷天堂| 日韩美女毛茸茸| 最近的2019中文字幕免费一页| 麻豆精品精华液| 高潮白浆女日韩av免费看| 久久国产精品久久久久久久久久| 亚洲欧美激情在线视频| 欧美日韩亚洲一区二区三区| 国产精品免费久久久久久| 日本高清视频一区| 91国内揄拍国内精品对白| 亚洲性视频网站| 久久久中精品2020中文| 日韩美女视频在线观看| 日韩美女在线观看一区| 91精品国产高清久久久久久| 亚洲人成网站色ww在线| 日韩欧美在线看| 亚洲国产精品va| 92国产精品视频| 亚洲www在线| 亚洲人成伊人成综合网久久久| 91精品国产综合久久男男| 国产成人精品综合久久久| 欧洲成人在线视频| 国产精品视频内| 国产日韩精品在线观看| 精品国偷自产在线视频| 亚洲欧美日韩一区二区在线| 一级做a爰片久久毛片美女图片| 日韩视频在线观看免费| 亚洲精品视频在线播放| 欧美日韩国产精品一区二区不卡中文| 国产视频精品免费播放| 亚洲风情亚aⅴ在线发布|