2018-07-03---Angular2 Form表单(转载)

ng2的表单有三个重要概念

1 FormControl

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

FormControl 和 FormGroup

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

let name = nameControl.value; //kate

nameControl.errors //StringMap(string, any) of errors

nameControl.dirty //false

nameControl.valid //true

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

name: new FormControl("issliu"),
job: new FormControl('web front end develpoer'),
zip: new FormControl("200000")})

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

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

import {FORM_DIRECTIVES} from '@angular/forms';
//FORM_DIRECTIVES 模块中包含了一系列常用的表单指令,只要我们在component的directives中引用了它,就可以在对应的template中使用这些指令
@Component({
    selector: "test-form",
    directives: [FORM_DIRECTIVES],
    template: `
` }) 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'.
现在我们把这个组件引用到模板中:

这里,我们显示的指明了表单的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,可以这么写


如果需要验证FormGroup的某一项,那就这么写

现在,让我们来自定义一个Validator吧!

function skuValidator(control:FormControl): {[s:string]: boolean} {
  if(control.value.test(/^123/)) {
        return  {invalidSku: true}
      }
}

定义Validator有三个关键点:
它接受一个FormControl作为参数,同时返回一个StringMap对象,如果这个boolean值为真表明验证通过,否则表明出错。
现在我们把这个验证项加入myForm:

    this.myForm = fb.Group({
        'sku': ['', Validator.compose([
            validators.required, skuValidator
        ])]
    })

ok,大功告成,现在我们在模板中可以使用:

来检测是否通过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)
        }
    )

你可能感兴趣的:(2018-07-03---Angular2 Form表单(转载))