ng2 学习笔记(二)表单及表单验证

在上一篇文章中提到了表单,只说了表单的数据绑定,这一篇文章主要讲一下表单验证,为什么把表单单独拿出来学习,主要是因为,表单是商业应用的支柱,我们用它来执行登录、求助、下单、预订机票、安排会议,以及不计其数的其它数据录入任务,使用频率非常高。所以这块的重要性就显而易见了。

正文开始,这篇文章还是适合初学者,如果是大神,请指正不足:

先来看一下最终的样子:

表单很简单,模拟新增客户,用到表单的不少控件,

首先,要使用angular 的表单的一些控件,在使用ngModel做双向数据绑定之前,得先导入FormsModule, 把它加入 Angular 模块的imports列表。

在加载之前写组件。app.module.ts主文件代码如下:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { FormsModule } from '@angular/forms'; //引入表单模块
import { AppComponent }  from './app.component';
import { UserForm } from './form.component'; // 引入自定义的组件

@NgModule({
  imports:      [ BrowserModule ,FormsModule],
  declarations: [ AppComponent,UserForm],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

下面我们主要看一下表单这个组件内部的一些细节:

 1 import { Component } from '@angular/core';
 2 
 3 @Component({
 4     selector:'hero-form',
 5     template:`
 6         <h2>FORM 表单</h2>
 7         <hr />
 8         <div class="container">
 9             <div class="row">
10                 <div class="col-sm-6 col-sm-offset-3">
11                     <h4>客户管理</h4>
12                     <form #forms="ngForm">
13                         <div class="alert alert-danger" [hidden]="forms.form.valid">表单填写不合法</div>
14                         <div class="form-group">
15                             <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label>
16                             <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
17                         </div>
18                         <div class="form-group">
19                             <label [class.text-danger]="!sex.valid && forms.form.controls.sex.touched">性别</label>
20                             <select class="form-control" [(ngModel)]="model.sex" required name="sex" #sex="ngModel">
21                                 <option *ngFor="let s of sexs" [ngValue]="s">{{s}}</option>
22                             </select>
23                         </div>
24                         <div class="form-group">
25                             <label>来源</label>
26                             <div>
27                                 <label class="checkbox-inline" *ngFor="let f of froms">
28                                       <input type="radio" [value]="f" name="from" [(ngModel)]="model.from" #from="ngModel" required> {{f}}
29                                 </label>
30                             </div>
31                         </div>
32                         <div class="form-group">
33                             <label>意向产品</label>
34                             <div>
35                                 <label class="checkbox-inline" *ngFor="let p of model.mayBuy">
36                                       <input type="checkbox" [(ngModel)]="p.chose" [value]="p.pid" name="mayBuy" required> {{p.pname}}
37                                 </label>
38                             </div>
39                         </div>
40                         <button type="button" (click)="submit(forms.form)" [class.btn-danger]="!forms.form.valid" [disabled]="!forms.form.valid" class="btn btn-primary">提交</button>
41                     </form>
42                 </div>
43             </div>
44         </div>
45     `
46 }) //这里有个小坑,如果这里按习惯加一个分号“;”,那就挂了,不能编译
47 
48 export class UserForm {
49     sexs = ['男', '女','保密'];
50     products = [
51         {
52             pid:'p_001',
53             pname:'产品A',
54             chose:false
55         }, 
56         {
57             pid:'p_001',
58             pname:'产品B',
59             chose:false
60         },
61         {
62             pid:'p_001',
63             pname:'产品C',
64             chose:false
65         },
66         {
67             pid:'p_001',
68             pname:'产品D',
69             chose:false
70         }
71     ];
72     froms = ['新增客户','老客户介绍'];
73       model = {
74           name:'',
75           sex:'',
76           from:'',
77           mayBuy:this.products
78       };
79       submitted = false;
80 
81       submit(a:any){
82           console.log(this.model,a)
83       }
84 }

普通表单结构以及数据的双向绑定,就不多说了,主要说一下表单验证这块,即红色代码的地方。

交代一下基础概念,在ng 的表单模块中,单个控件(如:input)都会被跟踪状态,并且会在该控件上增加相应的class:

  1)、控件是否已经被访问过:

      是:touched;class:ng-touched

      否:untouched; class:ng-untouched

  2)、控件的值是否被修改过:

      是:dirty;class:ng-dirty

      否:pristine;class:ng-pristine

  3)、控件的值是否合法:

      是:valid;class:ng-valid

      否:invalid;class:ng-invalid

整体表单也存在以上的3中状态,表单的验证证是通过这些跟踪的不同状态完成的。那么怎么访问到这些状态呢?

你可能已经注意到在form标签上有这样一段代码:

<form #forms="ngForm">

是的,#forms这个就是模版引用变量,上一篇文章提到过,这里只是把#forms初始化为 "ngForm";
现在我们就可以通过forms这个对象访问到我们需要的状态了,如果你不知道forms里都有啥,怎么用,那你就写个方法,把它打印出来,(click)="submit(forms)" 就可以了。
还有一个要注意的点,就是针对类似
<input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
这样的,name属性是必须要添加的,如果要对单个控件进行验证,我们可以加上模版引用变量#name="ngModel"快速访问到这个控件。
如果你需要正则表达式验证,只需加入pattern属性即可;
<input type="text" class="form-control" pattern="[a-zA-Z ]*" [(ngModel)]="model.name" name="name" />

以上述代码为例主要有以下几个点:

1、整体表单的合法性验证:

  代码:forms.form.STATE,例如:forms.form.valid;forms.form.invalid

2、单个表单控件验证:

  以这段代码为例:  

1 <div class="form-group">
2   <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label>
3   <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
4 </div>

这里的label的显示样式的判断条件其实是两种判断方法,

  1)、!name.valid这个是使用模板引用变量来判断的;

  2)、forms.form.controls.name.touched是使用forms.form这个对象判断的。

注意:forms.form这个对象里有很多子对象,这里使用的是form下controls这个对象查找到name判断的,至于是否应该controls这个子对象,有待研究。

 

本文到此结束,只是表单的一些初级应用,如果想了解更多,请点击这里查看API文档。

欢迎大家对本文所涉及的内容进行探讨,对有误的地方进行指正。

感谢阅读。

 

posted @ 2017-02-23 10:49  一步小僧  阅读(2207)  评论(0编辑  收藏  举报
一步小僧哈哈