模板驅動表單學習

建立User模型類建立表單組件頁面測試總結參考文獻javascript

Angular知識學習(一)中有講述到表單的知識,不過那是最基礎的演示,在以後的學習中又瞭解到模板驅動表單,因此考慮對以前的表單案例進行重構,完善表單功能,讓案例更接近應用。css

根據官網模板驅動表單的知識內容,咱們從新構建人員登記表單,主要分爲如下步驟:html

  1. 建立 Uuser 模型類
  2. 建立控制此表單的組件
  3. 建立具備初始表單佈局的模板。
  4. 使用 ngModel 雙向數據綁定語法把數據屬性綁定到每一個表單輸入控件。
  5. 往每一個表單輸入控件上添加 name 屬性 (attribute)。
  6. 添加自定義 CSS 來提供視覺反饋。
  7. 顯示和隱藏有效性驗證的錯誤信息。
  8. 使用 ngSubmit 處理表單提交。
  9. 禁用此表單的提交按鈕,直到表單變爲有效。

建立User模型類

使用 Angular CLI 命令 ng g class 生成一個名叫 Uuer 的新類: java

ng g class model/uuer
複製代碼

內容以下:nginx

export class Uuser {

  constructor(
    public name: string,
    public sex: string,
    public city: string,
    public hobbies: any[],
    public remark: string
  ) {

  }
}
複製代碼

該類主要包含五個屬性,分別是姓名、性別、城市、愛好和備註。其中愛好有多個,因此用數組來表示。web

建立表單組件

使用 Angular CLI 命令 ng g component 生成一個名叫 UserForm 的新組件: bootstrap

ng g component components/userForm
複製代碼

由於模板驅動的表單位於它們本身的模塊,因此在使用表單以前,須要將 FormsModule 添加到應用模塊的 imports 數組中。對 app.module.ts 進行修改:數組

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

  imports: [
    BrowserModule,
    FormsModule
  ]
複製代碼

有兩處更改app

  1. 導入 FormsModule
  2. FormsModule 添加到 ngModule 裝飾器的 imports 列表中,這樣應用就能訪問模板驅動表單的全部特性,包括 ngModel

關於表單內容的分析,官方文檔寫的很是詳細,這裏我只針對本案例中的難點進行分析,其餘細節部分能夠閱讀官方文檔。框架

user-form.component.html內容以下:

<h2>人員登記系統</h2>
<div class="container">
  <div [hidden]="submitted">
    <form (ngSubmit)="onSubmit()" #form="ngForm">
      <div class="form-group">
        <label for="name">姓 名</label>
        <input class="form-control" id="name" type="text" required name="name" [(ngModel)]="user.name" #name="ngModel">
        <span [hidden]="name.valid || name.pristine" class="alert alert-danger">Name is required</span>
      </div>

      <div class="form-group">
        <label>性 別 </label> &nbsp;
        <div class="radio-inline">
          <input type="radio" value="男" name="sex" id="man" [(ngModel)]="user.sex" > <label for="man"></label>
        </div>
        <div class="radio-inline">
          <input type="radio" value="女" name="sex" id="woman" [(ngModel)]="user.sex" > <label for="woman"></label>
        </div>
      </div>

      <div class="form-group">
        <label for="city">城 市</label>
        <select class="form-control" id="city" required name="city" [(ngModel)]="user.city" #city="ngModel">
          <option *ngFor="let ct of cities" [value]="ct">{{ct}}</option>
        </select>
        <span [hidden]="city.valid || city.pristine" class="alert alert-danger">City is required</span>
      </div>

      <div class="form-group">
        <label for="hobby">愛 好</label>&nbsp;
        <span *ngFor="let item of user.hobbies;let key=index" class="checkbox-inline">
          <input type="checkbox" [id]="'check'+key" [(ngModel)]="item.status" [name]="'check'+key"><label [for]="'check'+key">{{item.title}}</label>
          &nbsp;&nbsp;
        </span>
      </div>

      <div class="form-group">
        <label for="remark">備 注</label>
        <textarea class="form-control" id="remark" type="text" required name="remark" [(ngModel)]="user.remark" #remark="ngModel"></textarea>
        <span [hidden]="remark.valid || remark.pristine" class="alert alert-danger">remark is required</span>
      </div>

      <button type="submit" class="btn btn-success" [disabled]="!form.valid">Submit</button>
      <button type="button" class="btn btn-default" (click)="newUser();form.reset()">New User</button>

    </form>
  </div>

  <div [hidden]="!submitted">
    <h2>You submitted the following:</h2>
    <div class="row">
      <div class="col-xs-3">姓 名</div>
      <div class="col-xs-9">{{ user.name }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">性 別</div>
      <div class="col-xs-9">{{  user.sex }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">城 市</div>
      <div class="col-xs-9">{{  user.city }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">愛 好</div>
      <div class="col-xs-9">
        <span *ngFor="let item of user.hobbies">
          <span *ngIf="item.status == 1">{{item.title}}</span>&nbsp;&nbsp;
        </span>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-3">備 注</div>
      <div class="col-xs-9">{{  user.remark }}</div>
    </div>
    <br>
    <button class="btn btn-primary" (click)="submitted=false">Edit</button>
  </div>
</div>
複製代碼

同官方文檔中案例相比,本文的案例增長了單選框和多選框的應用,尤爲是多選框,考慮到數據的雙向綁定,因此必須對 user.hobbies 屬性進行初始化,經過勾選前臺按鈕,來改變 user.hobbies的狀態值,從而達到信息記錄的目的。

user-form.component.ts內容以下:

import { Component, OnInit } from '@angular/core';
import { Uuser } from '../../model/uuser';

@Component({
  selector'app-user-form',
  templateUrl'./user-form.component.html',
  styleUrls: ['./user-form.component.css']
})
export class UserFormComponent implements OnInit {

  submitted = false;
  cities = ['北京''上海''廣州 ''深圳''杭州''武漢''成都'];
  hobbies = ['唱歌''跳舞''跑步''健身''游泳'];

  user = new Uuser('''男'this.cities[1], [], '');
  constructor() { }

  ngOnInit(): void {
    this.setHobbies();
  }

  //每一個User對象都初始化hobby屬性,只是status值默認爲0,經過前臺勾選來修改status
  setHobbies() {
    // tslint:disable-next-line: prefer-for-of
    for (let i = 0; i < this.hobbies.length; i++) {
      this.user.hobbies.push(
        {
          titlethis.hobbies[i],
          status0
        }
      );
    }
  }

  onSubmit() {
    this.submitted = true;
  }

  newUser() {
    this.user = new Uuser('''''', [], '');
    this.setHobbies();
  }

}
複製代碼

爲了增長前臺表單的觀賞性,對錶單的 CSS 樣式作了一些修改。

首先是 styles.css,引入 Bootstrap 樣式,對錶單總體框架顯示進行優化。

@import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css');
複製代碼

其次是 user-form.component.css

h2{
  text-align: center;
}
.ng-valid[required].ng-valid.required  {
  border-left5px solid #42A948/* green */
}

.ng-invalid:not(form)  {
  border-left5px solid #a94442/* red */
}
複製代碼

能夠在輸入框的左側添加帶顏色的豎條,當在必填字段輸入有效內容時,輸入框左側會變爲綠色,不然視爲無效,變爲紅色。

頁面測試

對上述的代碼進行驗證,首先完整走一遍邏輯過程。

咱們來梳理一下流程,首先是維護一我的的基本信息,點擊 Submit 按鈕提交表單,即跳轉到人員信息查看頁面,再點擊 Exit 按鈕退回到人員維護頁面,點擊 New User 按鈕,清空頁面內容,從新錄入人員信息,再次提交表單可正常跳轉到人員信息查看頁面。

測試過程當中能夠發現,當必填項不填寫內容,Submit 按鈕始終是灰色的,即沒法點擊提交,此處是對整個表單進行有效驗證,在實際應用中也是頗有必要的。

關於性別單選框有一點須要注意:平時咱們設置單選框的默認值,加上 checked 便可,可是因爲在當前案例中使用了雙向數據綁定,因此該屬性不起做用,必須給 user.sex 設置默認值,從而實現單選框的默認選定。

關於愛好多選框,從數據雙向綁定的角度來看,是沒法向 user.hobbies 中增長數據,多選框的勾選只是狀態值的改變,因此在 user-form.component.ts 文件中會增長一個 setHobbies 方法。

總結

本文對於 Angular 表單的使用進行了優化,利用框架特性來支持數據修改、驗證和更多操做:

  • Angular HTML 表單模板。
  • 帶有 @Component 裝飾器的表單組件類。
  • 經過綁定到 NgForm.ngSubmit 事件屬性來處理表單提交。
  • 模板引用變量,例如 #form#name
  • [(ngModel)] 語法用來實現雙向數據綁定。
  • name 屬性的用途是有效性驗證和對錶單元素的變動進行追蹤。
  • 指向 input 控件的引用變量上的 valid 屬性,可用於檢查控件是否有效、是否顯示/隱藏錯誤信息。
  • 經過綁定到 NgForm 的有效性狀態,控制 Submit 按鈕的禁用狀態。
  • 定製 CSS 類來給用戶提供無效控件的視覺反饋。

參考文獻

官方文檔

相關文章
相關標籤/搜索