中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Angular2如何實現模板驅動的表單

發布時間:2021-08-17 14:41:57 來源:億速云 閱讀:156 作者:小新 欄目:web開發

這篇文章給大家分享的是有關Angular2如何實現模板驅動的表單的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

在網頁開發中,表單估計是最常用的一個,同時也是最麻煩、最容易出問題的。在一個稍微復雜一點的應用中,我們除了用表單元素收集數據,還需要驗證,幾個數據之間可能還會相互關聯,然后根據不同的數據值調用不同的業務邏輯等。

使用Angular提供的數據綁定的功能,我們可以很容易就在組件中獲得用戶輸入的數據,Angular也提供了幾種驗證方式方便我們進行數據的校驗。但是,一些自定義的數據驗證、數據交互和業務邏輯還是需要自己處理。

在Angular2中,提供了2種表單實現方式,分別是'template-driven'(模板驅動的表單)和'model-driven'(模型驅動表單)。在這篇文章中,我們先來看看模板驅動的表單。顧名思義,模板驅動的表單就是大部分表單相關代碼都在模板里,通過在模板里面添加ngForm, ngModel和ngModelGroup等屬性來定義模板和驗證信息,以及它跟組件之間的數據交互。

實例

下圖是這篇文章使用的實例的界面:

Angular2如何實現模板驅動的表單

它是一個用戶信息輸入的表單,包括4個字段,用戶名、電話、城市和街道,演示了如何使用表單,給各個字段添加驗證并顯示驗證結果,以及如何在組件中判斷是否出錯并獲取出錯信息。

項目源碼可以從github獲取,這個項目包含了幾個Angular2表單相關的實例,可以使用下面的命令獲取本文所對應的代碼:

git clone https://github.com/Mavlarn/angular2-forms-tutorial

然后進入項目目錄,運行下面的命令安裝依賴然后運行測試服務器

cd angular2-forms-tutorial
git checkout template-driven # 檢出該文所使用的tag
npm install
npm start

該項目是基于之前的Angular2-basic模板,這個教程相關的代碼都在'template-forms'目錄里面。

引入FormsModule

首先,我們需要在app.module.ts里引入FormsModule。

import { FormsModule } from '@angular/forms';
//省略其他
@NgModule({
 imports: [ BrowserModule, FormsModule ],
 //省略其他
})

初始表單

然后,我們從一個基本的html表單開始:

<form>
 <label>姓名:</label>
 <input type="text">
 <label>電話:</label>
 <input type="text">
 <label>城市:</label>
 <input type="text">
 <label>街道:</label>
 <input type="text">
 <button type="submit">保存</button>
</form>

在實際的實例中,使用了bootstrap的表單樣式,一組輸入框應該是下面這個樣子,但是在本文中,為了節省頁面顯示的篇幅,我省略了div, form-group等,我們只需要關心如何在Angular2中使用模板驅動的表單。如果想查看完整的帶樣式的代碼,請查看源文件。

<div class="form-group">
  <label class="col-sm-2 control-label">姓名:</label>
  <div class="col-sm-10">
    <input class="form-control" type="text">
  </div>
</div>

ngForm

在上面的表單里,我們沒有使用Angular2的任何功能,如數據綁定,也沒有使用其他指令。但是,Angular2在<form>上實現了一個指令'ngForm',這樣,對于所有的html的form表單,都會使用ngForm組件去初始化該表單。

使用ngForm對象

接下來,我們需要在模板里面訪問這個ngForm的實例,這樣我們就能夠從這個實例里面獲取數據,或者獲取數據驗證狀態。
在Angular2里,都提供了一個模板引用變量的功能,通過#加變量實現。通過這個功能,我們可以在同一元素、兄弟元素或任何子元素中引用模板引用變量。這樣聽著還是不好理解,我們看一個例子:

<input #phone placeholder="phone number">
<button (click)="callPhone(phone.value)">Call</button>

在這個例子中,我們通過#phone定義了一個變量,它所指的就是這個input元素,phone.value也就是這個輸入框輸入的值。

除了使用#,也可以使用ref-,例如ref-phone形式的定義跟#phone是一樣的。

我們可以對任何的DOM元素使用這種方式獲取當前引用,也可以對任何的Angular2的指令使用。在這個表單的例子中,我們這樣來獲取這個ngFrom的引用:

<form #userForm="ngForm">

其中'ngForm'就是當前這個指令,這樣在這個模板里面,我們可以用userForm獲得表單的所有數據。

提交表單

在html中,我們要提交一個form,會在form里寫一個action的屬性,然后,用一個類型為'submit'的按鈕來提交。但是,在Angular2中,我們需要使用ngSubmit事件:

<form #userForm="ngForm" (ngSubmit)="logForm(userForm)">
  <button type="submit">保存</button>
</form>

這樣,當用戶點擊保存按鈕的時候,Angular2會使用自己的驗證機制,驗證所有的數據,然后在調用'logForm(userForm)'方法。

在我們的組件中,實現這個方法:

logForm(theForm: NgForm) {
  console.log(theForm.value);
  if (theForm.invalid) {
    // handle error.
  }
}

在這個方法里,我們使用theForm.invalid就可以獲得這個表單是否驗證成功的狀態,也可以用'theForm.value'獲得所有的表單數據。在這里,我們把表單數據打印到控制臺來檢查數據。至于如何從這個表單引用中獲取控件數據和狀態,會在接下來再講。

使用ngModel綁定數據

接下來,我們需要綁定數據。假設我們的業務是打開這個頁面的時候獲取用戶數據,然后顯示到頁面表單上。我們在組件的構造方法中創建一個模擬的用戶數據:

export class TemplateFormsComponent {
  user: any;
  constructor() {
    this.user = {
      name: '張三',
      mobile: 13800138001,
      city: '北京',
      street: '朝陽望京...'
    };
  }
}

然后在模板中將這個組件中的數據綁定到模板頁面上:

<input type="text" name="name" [(ngModel)]="user.name">
<input type="text" name="mobile" [ngModel]="user.mobile">
<input type="text" name="city" [ngModel]="user.city">
<input type="text" name="street" [ngModel]="user.street">
<!-- 其他的輸入框都類似 -->

在這里,我們使用[(ngModel)]="user.name",這是雙向綁定的方式,這樣,當我們修改頁面上的數據的時候,在組件中也能獲得更新后的數據;同時,如果在組件中更新了數據,在頁面上也能更新。

為了演示這個雙向綁定跟單向綁定的區別,我們只對姓名使用雙向綁定,對其他的都是用單向綁定,也就是[ngModel]="user.mobile"。使用[]的單向綁定是從模板到組件的綁定,也就是頁面中的輸入的數據改變,組件中的數據也會改變。但是組件中的數據更新不會引起頁面上該數據的更新。

使用單向綁定可以減少數據的更新檢查,從來可以提高性能。

如果不需要數據的初始化,我們其實可以只用ngModel,例如:

<input type="text" name="city" ngModel>

這樣,我們在組件中創建的用戶數據就無法顯示到頁面上,但是,他還是能夠將頁面上輸入的數據綁定到組件中的數據上。

在Angular2中,使用ngModel結合name屬性來創建一個表單控件FormControls。例如上面的<input name="city" ngModel>就對應一個userForm里面的控件city。由于我們在提交方法里面將這個userForm作為參數傳到方法里,我們可以在方法里面獲得所有的表單控件theForm.controls,它是一個Map類型的對象,key是所有的表單元素的name,值就是一個FormControl對象,里面保存著數據、和驗證結果、是否修改等狀態。也正是因為這些FormControls,我們才能夠使用theForm.value的方式獲取表單里的數據。當我們點擊保存按鈕的時候,就能在日志里面看到表單的數據:

{
  name: "張三",
  mobile: 13800138001,
  city: "北京",
  street: "朝陽望京..."
}

使用ngModelGroup分組顯示

一般情況下,我們的model數據有可能是嵌套的,比如對于用戶信息來說,城市和街道可能在一個地址對象address里,例如:

{
  name: "張三",
  mobile: 13800138001,
  address: {
    city: "北京",
    street: "朝陽望京..."
  }
}

對于這樣的數據,我們就可以使用ngModelGroup來分組。模板就是這樣:

<form #userForm="ngForm" (ngSubmit)="logForm(userForm)">
 <label>姓名:</label>
 <input type="text" name="name" [(ngModel)]="user.name">
 <label>電話:</label>
 <input type="text" name="mobile" [ngModel]="user.mobile">
 <fieldset ngModelGroup="address">
  <label>城市:</label>
  <input type="text" name="city" [ngModel]="user.address.city">
  <label>街道:</label>
  <input type="text" name="street" [ngModel]="user.address.street">
  <button type="submit">保存</button>
 </fieldset>
</form>

這樣我們就把地址信息都封裝到一個address對象里面。注意我們綁定的數據的結構也發生改變,這樣,我們也需要修改我們的組件里面的用戶數據:

export class TemplateFormsComponent {
  user: any;
  constructor() {
    this.user = {
      name: '張三',
      mobile: 13800138001,
      address: {
        city: '北京',
        street: '朝陽望京...'
      }
    };
  }
}

至此,我們的表單的基本功能就算完成了。我們在面板中創建了表單,在組件中初始化了用戶數據,并顯示到頁面上,在頁面上用ngModel,將頁面上的數據更改綁定到組件上。同時,使用name屬性,使得表單里面的所有數據都成為FormControl對象。在提交所調用的方法里,獲得了表單的驗證狀態和數據。

表單控件的驗證和狀態

下一步,我們來添加數據驗證,Angular2為我們提供了幾種最基本的驗證:

  • required:表明該數據是必須的。

  • minlength:設置該字段的長度的最小值,即使輸入的是數字,也按照字符串來判斷長度。

  • maxlength:設置該字段的長度的最大值。

  • pattern:使用正則表達式驗證

在使用Angular的驗證之前,我們首先需要關閉瀏覽器默認的驗證,不然,如果某一個輸入不合法,提交按鈕就無法提交。我們在form里添加novalidate:

<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate>

然后,我們對姓名輸入框添加驗證,并根據驗證的結果顯示不同的提示,同時,為了演示Angular2表單控件的特性,再添加幾個提示,來顯示該值的狀態,代碼如下:

<input type="text" name="name" [(ngModel)]="user.name" #name="ngModel" required minlength="3">
<span *ngIf="name.pristine" class="label label-primary">未修改</span>
<span *ngIf="name.dirty" class="label label-warning">已修改</span>
<span *ngIf="name.valid" class="label label-success">有效</span>
<div [hidden]="name.valid || name.pristine" class="alert alert-danger">
  <p *ngIf="name.errors?.minlength">姓名最小長度為3</p>
  <p *ngIf="name.errors?.required">必須輸入姓名</p>
</div>

首先,我們在input上添加了2個驗證,required和minlength="3"。

其次,我們使用#name="ngModel"創建了一個模板引用變量,這樣我們在下面就可以使用name來獲取這個表單控件(FormControl)的引用。表單控件有一些屬性,如pristine, dirty, valid, touched,這幾個都是狀態類型,表示某一種狀態是否為真。除此以外還有控件的值可以用name.value獲取。最后,還有驗證的錯誤信息結果,會放在name.errors里。

在上面的代碼里,我們用<span *ngIf="name.pristine" class="label label-primary">未修改</span>,在控件值未被修改的時候,顯示一個lebel。同樣,在被修改、驗證有效的時候顯示相應的標簽。

最后,所有的驗證結果的錯誤信息會保存在name.errors里,如果沒有數據驗證錯誤,這個errors值就是null,所以,在上面的代碼里,我們用name.errors?.minlength,這表示,如果errors不為null,而且errors.minlength也不為空的時候,才顯示里面的信息。

我們可以看到,表單控件的驗證會將驗證器的名字作為key放在errors里面,對應的值是true。我們就是用這個特性,來根據控件驗證的不同結果,來顯示友好的錯誤信息。

如果運行我們的實例,可以發現,對于姓名,如果清空它的值,發現只有一個錯誤信息,就是必須輸入姓名。你可能會覺得,這時候,值為空,那他的長度也小于3,那么minlength這個錯誤也應該被檢測到才對,但是實際上,遇到第一個錯誤以后,就沒有其他的驗證。

在上面姓名輸入框上,我們使用#name="ngModel"創建了一個模板引用變量,然后在接下來的模板里面使用它獲得表單控件。實際上,我們也可以直接使用之前定義的對ngForm的引用,來獲得這個表單里所有控件的狀態。例如,對電話,我們使用下面的方式:

<input type="text" name="mobile" [ngModel]="user.mobile" required minlength="11" maxlength="11">
<span *ngIf="userForm.controls.mobile?.pristine" class="label label-primary">未修改</span>
<span *ngIf="userForm.controls.mobile?.dirty" class="label label-warning">已修改</span>
<span *ngIf="userForm.controls.mobile?.valid" class="label label-success">有效</span>
<div [hidden]="userForm.controls.mobile?.valid || userForm.controls.mobile?.pristine" class="alert alert-danger">
  <p *ngIf="userForm.controls.mobile?.errors?.minlength">電話長度必須為11</p>
  <p *ngIf="userForm.controls.mobile?.errors?.required">必須輸入電話</p>
</div>

在這里,我們沒有獲取對mobile的模板引用,而是用ngForm的引用獲得:

userForm.controls.mobile?.pristine

當獲取驗證錯誤結果時:

userForm.controls.mobile?.errors?.minlength

注意這里在mobile上就使用?是因為,在使用ngIf渲染頁面上的元素的時候,這個表單控件還沒有初始化完成,如果不加這個?,就會出現錯誤。

根據驗證狀態定義樣式

Angular的表單驗證,除了在控件上的數據以外,它還會根據狀態在控件所在的html元素上添加css樣式:

Angular2如何實現模板驅動的表單

所以,我們只需要定義相關的css,就可以實現根據狀態顯示不同的效果。

.ng-valid[required], .ng-valid.required {
 border-left: 5px solid #42A948; /* green */
}
.ng-invalid:not(form).ng-invalid:not(fieldset) {
 border-left: 5px solid #a94442; /* red */
}

結合各種css的選擇器,我們就可以根據表單控件的狀態實現各種顯示的樣式。

在組件中獲取表單控件數據

最后,我們再看看怎樣在組件中獲取這些控件的狀態和結果,在上面,我們給ngForm添加了一個提交方法:

<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate>

然后在組件中,這個logForm(userForm)方法如下:

logForm(theForm: NgForm) {
  if (theForm.invalid) {
    if (theForm.controls['name'].errors) {
      this.nameErrorMsg = 'name error:' + JSON.stringify(theForm.controls['name'].errors);
    } else {
      this.nameErrorMsg = null;
    }
  }
  console.log(theForm.value);
}

在這個方法里,theForm就是ngForm的模板引用實例,類型是NgForm的。

如果表單驗證有失敗,theForm.invalid就是false。

theForm.controls就是這個表單里的所有控件,如果想獲取姓名的驗證結果,就是theForm.controls['name'].errors。

用這種方式,我們就可以在組件中獲取所有表單控件的數據、驗證狀態、錯誤信息等。

重置表單

一般情況下,如果是新建用戶信息,我們需要在保存成功以后,清空當前數據,重置表單的狀態,等待用戶重新輸入。如果我們只是清空數據,這時候那些驗證錯誤就會被檢測到,我們我們需要將表單控件也都重置成未修改狀態。這在Angular2里很簡單,它提供了一個reset方法。

我們在里面添加一個重置按鈕:

<button (click)="reset(userForm)">重置</button>

然后在組件里:

reset(theForm: NgForm) {
  theForm.reset();
  return false;
}

注意我們需要讓這個方法返回false,這樣他就不會觸發submit的方法。

在官方的文檔中,還提供了另一種技巧來實現這種重置,就是在form上使用ngIf:

<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate *ngIf="active">

只有在active為true時這個表單才會創建。

然后在重置的時候,設置這個active為false,這樣這個表單就會被銷毀,然后用setTimeout的方式再設置它為true,這個表單就會重新創建,這樣就實現了重置的效果。

reset() {
  this.user = { // 重置用戶數據
    address: {}
  };
  this.active = false;
  setTimeout(() => this.active = true, 0);
  return false;
}

感謝各位的閱讀!關于“Angular2如何實現模板驅動的表單”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

文山县| 桐城市| 惠来县| 延边| 会宁县| 二连浩特市| 舟山市| 太和县| 奈曼旗| 衡南县| 辽阳市| 那坡县| 涞源县| 清丰县| 灵武市| 日照市| 小金县| 江孜县| 霍州市| 炎陵县| 德保县| 凌云县| 奉节县| 乌什县| 隆德县| 安新县| 尉犁县| 雷波县| 来宾市| 南丰县| 金华市| 曲周县| 沙湾县| 项城市| 酉阳| 内江市| 荔波县| 咸宁市| 邯郸县| 潼南县| 清徐县|