angular6的响应式表单的实现
1:在AppModule模块里面引入ReactiveFormsModule
要使用响应式表单,就要从@angular/forms包中导入ReactiveFormsModule,并把它添加到你的NgModule的imports数组中。
import{ReactiveFormsModule}from'@angular/forms'; @NgModule({ imports:[ //otherimports... ReactiveFormsModule ], }) exportclassAppModule{}
2:创建一个新的组件
nggcNameEditor
3:请在组件中导入FormControl类
FormControl类是angular响应式表单最基本的构造快,要注册单个的表单控件,请在组件中导入FormControl类,并创建一个FormControl的新实例,把它保存在某个属性里面。
import{Component}from'@angular/core'; import{FormControl}from'@angular/forms'; @Component({ selector:'app-name-editor', templateUrl:'./name-editor.component.html', styleUrls:['./name-editor.component.css'] }) exportclassNameEditorComponent{ name=newFormControl(''); }
4:在组件的模板中注册一个表单控件
修改模板,为表单控件添加formControl绑定,formControl是由ReactiveFormsModule中的FormControlDirective提供的。
Value:{{name.value}}
使用这种模板绑定语法,把该表单控件注册给了模板中名为name的输入元素。这样,表单控件和DOM
元素就可以互相通讯了:视图会反映模型的变化,模型也会反映视图中的变化。
5:替换表单控件的值
FormControl提供了一个setValue()方法,他会修改这个表单控件的值。
js
updateName(){ this.name.setValue('Nancy'); }
html
Value:{{name.value}}
在这个例子中,你只使用单个控件FormControl,但是当调用FormGroup或FormArray的setValue()方法时,传入的值就必须匹配控件组或控件数组的结构才行
6:把表单控件分组
FormControl的实例能控制单个输入框所对应的控件,FormGroup可以控制一组FormControl实例的表单状态,当创建FormGroup时,其中的每一个控件都会根据名字进行跟踪
1>:创建新的组件
nggcProfileEditor
2>:导入FormGroup和FormControl类并且创建FormGroup实例
import{Component}from'@angular/core'; import{FormGroup,FormControl}from'@angular/forms'; @Component({ selector:'app-profile-editor', templateUrl:'./profile-editor.component.html', styleUrls:['./profile-editor.component.css'] }) exportclassProfileEditorComponent{ profileForm=newFormGroup({ firstName:newFormControl(''), lastName:newFormControl(''), }); }
现在这些单独的控件FormControl被收集到了一个控件组中FormGroup,FormGroup实例拥有和FormControl实例相同的属性(比如value、untouched)和方法(比如setValue())。
3>:关联FormGroup的模型和视图
FormGroup能追踪每个单独控件FormControl的状态和变化,如果其中某个控件的状态或值变化了,父控件也会一次新的状态变更或值变更事件
profileForm通过[formGroup]指令绑定到了form元素,在该模型和表单中的输入框之间创建了一个通讯层,FormControlName指令提供的formControlName属性把每个输入框和FormGroup中定义的表单控件绑定起来。
4>:关联FormGroup的模型和视图
html
js
onSubmit(){ console.warn(this.profileForm.value); }
form标签所发出的submit事件是原生DOM事件,通过点击类型为submit的按钮可以触发本事件
6:嵌套的表单组
js
profileForm=newFormGroup({ firstName:newFormControl(''), lastName:newFormControl(''), address:newFormGroup({ street:newFormControl(''), city:newFormControl(''), state:newFormControl(''), zip:newFormControl('') }) });
html
部分模型修改
html
js
updateProfile(){ this.profileForm.patchValue({ firstName:'Nancy', address:{ street:'123DrewStreet' } }); }
patchValue()方法要针对模型的结构进行更新。patchValue()只会更新表单模型中所定义的那些属性。
6:使用FormBuilder来生成表单控件
FormBuilder服务提供了一些便捷方法来生成表单控件。
FormBuilder在幕后也使用同样的方式来创建和返回这些实例,只是用起来更简单。下面会重构ProfileEditor组件,用FormBuilder来代替手工创建这些FormControl和FormGroup。
Step1-导入FormBuilder类
import{FormBuilder}from'@angular/forms';
Step2-注入FormBuild服务
constructor(privatefb:FormBuilder){}
Step3-生成表单控件
FormBuilder服务有三个方法:control()、group()和array()。这些方法都是工厂方法,用于在组件类中分别生成
FormControl、FormGroup和FormArray。
你可以使用group()方法,用和前面一样的名字来定义这些属性。这里,每个控件名对应的值都是一个数组,这个数组中的第一项是其初始值。你可以只使用初始值来定义控件,但是如果你的控件还需要同步或异步验证器,那就在这个数组中的第二项和
第三项提供同步和异步验证器。
import{Component}from'@angular/core'; import{FormBuilder}from'@angular/forms'; @Component({ selector:'app-profile-editor', templateUrl:'./profile-editor.component.html', styleUrls:['./profile-editor.component.css'] }) exportclassProfileEditorComponent{ profileForm=this.fb.group({ firstName:['张'], lastName:['娉'], address:this.fb.group({ street:[''], city:[''], state:[''], zip:[''] }), }); constructor(privatefb:FormBuilder){} }
7:简单的表单验证
如何把单个验证器添加到表单控件中,以及如何显示表单的整体状态。
Step1-导入验证器函数
import{Validators}from'@angular/forms';
响应式表单包含了一组开箱即用的常用验证器函数。这些函数接收一个控件,用以验证并根据验证结果返回一个错误对象或空值。
Step2-把字段设为必填
最常见的校验项是把一个字段设为必填项。本节描述如何为firstName控件添加“必填项”验证器。
在组件中,把静态方法Validators.required设置为firstName控件值数组中的第二项。
profileForm=this.fb.group({ firstName:['',Validators.required], lastName:[''], address:this.fb.group({ street:[''], city:[''], state:[''], zip:[''] }), });
HTML5有一组内置的属性,用来进行原生验证,包括required、minlength、maxlength等。虽然是可选的,不过你也可以在表单的输入元素上把它们添加为附加属性来使用它们。这里我们把required属性添加到firstName输入元素上。
这些HTML5验证器属性可以和Angular响应式表单提供的内置验证器组合使用。组合使用这两种验证器实践,可以防止在模板检查完之后表达式再次被修改导致的错误。
8:显示表单的状态
现在,你已经往表单控件上添加了一个必填字段,它的初始值是无效的(invalid)。这种无效状态冒泡到其父FormGroup中,也让这个FormGroup的状态变为无效的。你可以通过该FormGroup实例的status属性来访问其当前状态。
FormStatus:{{profileForm.status}}
9:使用表单数组管理动态控件
FormArray是FormGroup之外的另一个选择,用于管理任意数量的匿名控件,如果你事先不知道子控件的数量,FormArray是一个很好的选择
Step1-导入FormArray
import{FormArray}from'@angular/forms';
Step2-定义FormArray
为profileForm添加一个aliases属性,把它定义为FormArray类型。(FormBuilder服务用于创建FormArray实例。)
profileForm=this.fb.group({ firstName:['张',Validators.required], lastName:['以'], address:this.fb.group({ street:[''], city:[''], state:[''], zip:[''] }), aliases:this.fb.array([ this.fb.control('') ]) });
Step3-访问FormArray控件
通过getter来访问控件比较便捷,也容易复用
使用getter语法来创建一个名为aliases的类属性
getaliases(){ }
从父控件FormGroup中接收绰号的FormArray控件。
getaliases(){ returnthis.profileForm.get('aliases')asFormArray; } addAlias(){ this.aliases.push(this.fb.control('')); }
Step3-在模板中显示表单数组
在模型中定义了aliases的FormArray之后,你必须把它加入到模板中供用户输入,使用formArrayName在这个
FormArray和模板之间建立绑定。
Aliases
每当新的alias加进来时,FormArray就会基于这个索引号提供它的控件。这将允许你在每次计算根控件的状态和值时跟踪每个控件。
全部代码
html