Angular 4.x中表单Reactive Forms详解
Angular4.x中有两种表单:
- Template-DrivenForms-模板驱动式表单(类似于Angular1.x中的表单)
- ReactiveForms(Model-DrivenForms)-响应式表单
Template-DrivenForms(模板驱动表单),我们之前的文章已经介绍过了,了解详细信息,请查看-Angular4.xTemplate-DrivenForms。
Contents
- ngModuleandreactiveforms
- FormControlandFormGroup
- ImplementingourFormGroupmodel
- BindingourFormGroupmodel
- Reactivesubmit
- Reactiveerrorvalidation
- SimplifyingwithFormBuilder
Formbaseandinterface
Formbase
Signup
接下来我们要实现的功能如下:
- 绑定name、email、confirm输入框的值
- 为所有输入框添加表单验证功能
- 显示验证异常信息
- 表单验证失败时,不允许进行表单提交
- 表单提交功能
Userinterface
//signup.interface.ts
exportinterfaceUser{
name:string;
account:{
email:string;
confirm:string;
}
}
ngModuleandreactiveforms
在我们继续深入介绍reactiveforms表单前,我们必须在@NgModule中导入@angular/forms库中的ReactiveFormsModule:
import{ReactiveFormsModule}from'@angular/forms';
@NgModule({
imports:[
...,
ReactiveFormsModule
],
declarations:[...],
bootstrap:[...]
})
exportclassAppModule{}
友情提示:若使用reactiveforms,则导入ReactiveFormsModule;若使用template-driven表单,则导入FormsModule。
Reactiveapproach
我们将基于上面的定义的基础表单,创建SignupFormComponent:
signup-form.component.ts
import{Component}from'@angular/core';
@Component({
selector:'signup-form',
template:`
...
`
})
exportclassSignupFormComponent{
constructor(){}
}
这是一个基础的组件,在我们实现上述功能前,我们需要先介绍FormControl、FormGroup、FormBuilder的概念和使用。
FormControlandFormGroup
我们先来介绍一下FormControl和FormGroup的概念:
1、FormControl-它是一个为单个表单控件提供支持的类,可用于跟踪控件的值和验证状态,此外还提供了一系列公共API。
使用示例:
ngOnInit(){
this.myControl=newFormControl('Semlinker');
}
2、FormGroup-包含是一组FormControl实例,可用于跟踪FormControl组的值和验证状态,此外也提供了一系列公共API。
使用示例:
ngOnInit(){
this.myGroup=newFormGroup({
name:newFormControl('Semlinker'),
location:newFormControl('China,CN')
});
}
现在我们已经创建了FormControl和FormGroup实例,接下来我们来看一下如何使用:
Name: Location:
注意事项:Template-DrivenForms中介绍的ngModel和name=""属性,已经被移除了。这是一件好事,让我们的模板更简洁。
上面示例中,我们必须使用[formGroup]绑定我们创建的myGroup对象,除此之外还要使用formControlName指令,绑定我们创建的FormControl控件。
此时的表单结构如下:
FormGroup->'myGroup' FormControl->'name' FormControl->'location'
ImplementingourFormGroupmodel
signup.interface.ts
exportinterfaceUser{
name:string;
account:{
email:string;
confirm:string;
}
}
与之对应的表单结构如下:
FormGroup->'user' FormControl->'name' FormGroup->'account' FormControl->'email' FormControl->'confirm'
是的,我们可以创建嵌套的FormGroup集合!让我们更新一下组件(不包含初始数据):
import{Component,OnInit}from'@angular/core';
import{FormControl,FormGroup}from'@angular/forms';
@Component({...})
exportclassSignupFormComponentimplementsOnInit{
user:FormGroup;
ngOnInit(){
this.user=newFormGroup({
name:newFormControl(''),
account:newFormGroup({
email:newFormControl(''),
confirm:newFormControl('')
})
});
}
}
如果我们想要设置初始数据,我们可以按照上述示例进行设置。通常情况下,我们通过服务端提供的API接口来获取表单的初始信息。
BindingourFormGroupmodel
现在我们已经实例化了FormGroup模型,是时候绑定到对应的DOM元素上了。具体示例如下:
现在FormGroup与FormControl对象与DOM结构的关联信息如下:
//JavaScriptAPIs FormGroup->'user' FormControl->'name' FormGroup->'account' FormControl->'email' FormControl->'confirm' //DOMbindings formGroup->'user' formControlName->'name' formGroupName->'account' formControlName->'email' formControlName->'confirm'
当使用模板驱动的表单时,为了获取f.value表单的值,我们需要先执行#f="ngForm"的操作。而对于使用响应式的表单,我们可以通过以下方式,方便的获取表单的值:
{{user.value|json}}//{name:'',account:{email:'',confirm:''}}
Reactivesubmit
跟模板驱动的表单一样,我们可以通过ngSubmit输出属性,处理表单的提交逻辑:
...
需要注意的是:我们使用user对象作为onSubmit()方法的参数,这使得我们可以获取表单对象的相关信息,具体处理逻辑如下:
exportclassSignupFormComponent{
user:FormGroup;
onSubmit({value,valid}:{value:User,valid:boolean}){
console.log(value,valid);
}
}
上面代码中,我们使用Objectdestructuring(对象解构)的方式,从user对象中获取value和valid属性的值。其中value的值,就是user.value的值。在实际应用中,我们是不需要传递user参数的:
exportclassSignupFormComponent{
user:FormGroup;
onSubmit(){
console.log(this.user.value,this.user.valid);
}
}
表单的数据绑定方式和提交逻辑已经介绍完了,是该介绍表单实际应用中,一个重要的环节—表单验证。
Reactiveerrorvalidation
接下来我们来为表单添加验证规则,首先我们需要从@angular/forms中导入Validators。具体使用示例如下:
ngOnInit(){
this.user=newFormGroup({
name:newFormControl('',[Validators.required,Validators.minLength(2)]),
account:newFormGroup({
email:newFormControl('',Validators.required),
confirm:newFormControl('',Validators.required)
})
});
}
通过以上示例,我们可以看出,如果表单控制包含多种验证规则,可以使用数组声明多种验证规则。若只包含一种验证规则,直接声明就好。通过这种方式,我们就不需要在模板的输入控件中添加required属性。接下来我们来添加表单验证失败时,不允许进行表单提交功能:
... Signup
那么问题来了,我们要如何获取表单控件的验证信息?我们可以使用模板驱动表单中介绍的方式,具体如下:
{{user.controls.name?.errors|json}}
友情提示:?.prop称为安全导航操作符,用于告诉Angularprop的值可能不存在。
此外我们也可以使用FormGroup对象提供的API,来获取表单控件验证的错误信息:
{{user.get('name').errors|json}}
现在我们来看一下完整的代码:
import{Component,OnInit}from'@angular/core';
import{FormControl,FormGroup,Validators}from'@angular/forms';
import{User}from'./signup.interface';
@Component({
selector:'signup-form',
template:`
Nameisrequired