angular2 之 form表单

来源:互联网 发布:淘宝上市股票代码 编辑:程序博客网 时间:2024/05/16 07:03

<span style="font-family:Microsoft YaHei;"></span>

Angular2 重新设计了全新的表单模块,本文基于 angular rc.4 版本

ng2的表单有三个重要概念

1 FormControl //它封装了表单的inputs项,对外暴露为一个可以操作的FormControl对象

2 Validator //包括了一些常用的表单验证方法和一些工具函数,使得我们可以添加自定义的验证逻辑

3 Observers //检测表单的变动并执行相应的操作


FormControl 和 FormGroup

FormControl 代表单一的 input 输入域,它是 angular2/forms 的最小单元,在 FormControl中我们可以访问 input的值,当前的状态,例如是否 valid,是否 dirty,是否有 errors


在组件中创建一个FormControl:

<span style="font-family:Microsoft YaHei;">let nameControl = new FormControl("kate");let name = nameControl.value; //katenameControl.errors //StringMap(string, any) of errorsnameControl.dirty //falsenameControl.valid //true</span>

于是创建表单的过程就是创建一系列FormControl并添加相应的元数据和逻辑代码的过程。在模板中这样使用一个FormControl:

<input type="text" [formControl]="name"> //form 表单中某一行

这时我们就相当于在表单form的上下文环境中创建了一个新的FormControl对象。由于大部分表单都不止一个输入域,因此,我们需要有一种方式来管理多个 FormControl,同时还需要验证我们的表单,我们可以使用循环来遍历所有的FormControl来实现,但是这样会相当笨重而且复杂,没事,ng2为我们提供了 FormGroup来解决这个问题,下面我们创建一个FormGroup:

<span style="font-family:Microsoft YaHei;">let person = new FormGroup({name: new FormControl("issliu"),job: new FormControl('web front end develpoer'),zip: new FormControl("200000")})</span>


在实现上,FormGroup和FormControl都继承自AbstractControl抽象类,这意味着只要是在AbstraclControl中拥有的属性和函数在这两者之间都可以使用。因此,我们同样可以查看FormGroup的状态,值,变化检测等等。


下面我们来创建一个表单:

在创建表单之前,我们需要引入相应的依赖:

import {FormGroup, FormControl, FormBuilder, Validators, AbstractControl} from '@angular/forms';import {FORM_DIRECTIVES} from '@angular/forms';//FORM_DIRECTIVES 模块中包含了一系列常用的表单指令,只要我们在component的directives中引用了它,就可以在对应的template中使用这些指令@Component({selector: "test-form",directives: [FORM_DIRECTIVES],template: `<form #f="ngForm" (ngSubmit)="onSubmit(f.value)"><input name="sku" placeholder="sku"></input><button type="submit">submit</button></form>`})export class DemoForm {onSubmit(form:any):void{console.log('form data:', form);}}


这样,我们就实现了一个简单的表单。
详细解释:
这里可能会比较迷惑,因为我们并没有写什么指令在form上面,唯一的变化点在我们写了一个#f="ngForm"在form表单上面而已。
其实NgForm已经帮我们完成了这一切,在初始化Angular2表单时,只要我们引入了FORM_DIRECTIVES指令,它会自动检测form标签,如果form不包含
ngNoForm指令或者没有指定formGroup属性,则会自动为form表单应用NgForm指令,具体到细节就是绑定了一个名为ngForm的FormGroup到表单上。
这是一个非常有用的特性。当NgForm指令应用到form表单上后,它使得表单具有了以下两个功能:
1 一个名为 ngForm 的 FormGroup
2 表单具有一个 ngSubmit 的 @Output 属性
这里的#f="ngForm"表示我们使用了一个名为f的变量引用了这个表单对象,这样我们可以在模板的其他地方访问到它。
我们使用(ngSubmit)="onSubmit(f.value)"语句为表单绑定了一个提交行为,这个 onSubmit 方法是需要我们在对应的组件里面实现的。
这句话的意思是,当点击提交表单时,请调用组件的onSubmit方法。于是我们实现了一个具有一个input标签的可以提交的表单。
2 使用FormBuilder
ng2 为我们隐式构造FormControl 和 FormGroup 是非常简单快捷的。但是,如果我们希望自定义表单的行为怎么办?FormBuilder为我们很好的
解决了这个问题。
从命名上我们就可以看出,FormBuilder是用于帮助我们build表单的。前面我们提到表单是由FormControl和FormGroup组成的,这里我们可以把
FormBuilder理解为生产FormControl和FormGroup的工厂。
下面我们举例如何使用FormBuilder
我们需要引入REACTIVE_FORM_DIRECTIVE,这样才能在表单中使用formGroup和formControl指令。
import {FORM_DIRECTIVE, REACTIVE_FORM_DIRECTIVES,FormBuilder,FormGroup} from '@angular/form';@Component({selector: "demo-form-builder",templateUrl:'demo.html',directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES]})export class DemoFormBuilder{myForm: FormGroup;constructor(private fb: FormBuilder) {this.myForm = fb.group({'sku': ['ABC123']})}onSubmit(value){console.log(value);}}


这里我们在构造函数中注入了一个FormBuilder实例,这个FormBuilder实例具有两个主要的方法:
1 fb.control() //构造一个FormControl实例
2 fb.group() //构造一个FormGroup实例
上面的例子中,我们构造了一个名为myForm的FormGroup实例,这个group包含一个名为sku的control,默认值为'ABC123'.
现在我们把这个组件引用到模板中:
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)"><input [formControl]="myForm.controls['sku']"/><button type="submit">submit</button></form>


这里,我们显示的指明了表单的formGroup属性,因此ng2不会为表单自动应用NgForm指令了。
NgForm自动应用的form表单需要符合以下规则:
form:not([ngNoForm]):not([formGroup]), ngForm, [ngForm]
这意味着使用了ngNoForm属性的表单也不会应用NgForm
总结:
如果我们需要隐式的创建FormGroup和FormControl,请使用 ngFrom和ngModel //FORM_DIRECTIVES
如果需要绑定到一个已经存在的FormGroup和FormControl对象,请使用formGroup和formControl //REACTIVE_FORM_DIRECTIVES
3 添加验证:
在上面的DemoFormBuilder 类构造函数中,我们为this.myForm初始化值,现在改为:
this.myForm = fb.group({'sku': ['', Validators.required]})


我们已经可以在模板中通过myForm.controls['sku']来访问表单的sku值了,但是这样会在模板中写很多代码,最方便快捷的,是在组件内定义
一个实例变量用来引用名为sku的FormControl,例如
sku:AbstractControl;
this.sku = this.myForm.controls['sku'];
于是在模板中我们可以直接使用sku变量。这样做的好处,是在模板的任何一个地方我们都可以快速访问sku变量,但是如果是一个非常大的表单,
我们则需要在组件中初始化很多这样的变量,使得代码体验比较糟糕。
FormControl和FormGroup都具有hasError方法,
如果我们需要验证一个FormControl,可以这么写
<div *ngIf="sku.hasError('required')"></div>
如果需要验证FormGroup的某一项,那就这么写
<div *ngIf="myForm.hasError('required', 'sku')"></div>
现在,让我们来自定义一个Validator吧!
function skuValidator(control:FormControl): {[s:string]: boolean} {if(control.value.test(/^123/)) {return {invalidSku: true}}}


定义Validator有三个关键点:
它接受一个FormControl作为参数,同时返回一个StringMap<string, boolean>对象,如果这个boolean值为真表明验证通过,否则表明出错。
现在我们把这个验证项加入myForm:
this.myForm = fb.Group({'sku': ['', Validator.compose([validators.required, skuValidator])]})

ok,大功告成,现在我们在模板中可以使用:
<div *ngIf="myForm.hasError('skuValidator', 'sku')"></div>来检测是否通过Validator了
以上基本是angular表单中的主要功能,下面,我们还可以监听表单的变化:
同样,对于FormControl和FormGroup,都具有一个EventEmitter用来监听变动事件的。
我们通过调用control.valueChanges来获得他们的EventEmitter:
this.sku.valueChanges.subscribe((value: string) => {console.log("sku value changed", value)})this.myForm.valueChanges.subscribe((form: any) => {console.log("form chnged to:", form)})


OK,以上就是几个比较关键的ng2表单知识点。祝大家学习愉快,工作顺利。







0 0
原创粉丝点击