模板驱动表单学习

建立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 类来给用户提供无效控件的视觉反馈。

参考文献

官方文档

相关文章
相关标签/搜索