Angular2的内置指令可分为通用指令、路由指令、表单指令
表单常用:Validators(相应式表单验证用)、AbstractControlDirective(FormControl的抽象类)、 FormControl(每个表单控件都是一个FormControl)
表单指令分别被包含在下列三个模块中:(需要知道是就是一个表单控件就是一个FormControl)
- FormsModule (基本模板驱动表单)
- ReactiveFormsModule (响应式表单)
- InternalFormsSharedModule (表单控件类)
响应式表单是同步的。模板驱动表单是异步的。
使用响应式表单,我们会在代码中创建整个表单控件树。 我们可以立即更新一个值或者深入到表单中的任意节点,因为所有的控件都始终是可用的。
模板驱动表单会委托指令来创建它们的表单控件。 为了消除“检查完后又变化了”的错误,这些指令需要消耗一个以上的变更检测周期来构建整个控件树。 这意味着在从组件类中操纵任何控件之前,我们都必须先等待一个节拍。
具体有:
FormsModule(也包含InternalFormsSharedModule):
- NgForm、NgModel、NgModelGroup
ReactiveFormsModule(也包含InternalFormsSharedModule):
- FormControlDirective、FormControlName、FormArrayName
- FormGroupDirective、FormGroupName
InternalFormsSharedModule:
- DefaultValueAccessor、NumberValueAccessor、SelectControlValueAccessor、SelectMultipleControlValueAccessor、CheckboxControlValueAccessor、RadioControlValueAccessor
- NgSelectOption、NgSelectMultipleOption
- RequiredValidator、MinLengthValidator、MaxLengthValidator、PatternValidator
- NgControlStatus、NgControlStatusGroup
NgForm指令
所有的表单指令都需要在NgForm指令内部才能正常运行
NgForm指令是表单的控制中心,负责处理表单内的页面逻辑。这个指令可以不用在模板中显示使用,因为添加了FormsModule模块后,Angular模板在编译解析时,遇到<form>标签会自动创建一个NgForm指令并且将其添加到该<form>标签上。
NgModel指令
NgModel指令是表单数据绑定的核心,用于表单控件的数据绑定,提供了控件状态跟踪及校验功能。注意使用NgModel属性绑定时,一定要给该控件添加name属性。因为NgForm指令会为表单建立一个控件对象FormControl的集合,控件的NgModel属性绑定会以控件name作为唯一标识符来注册生成一个FormControl添加到集合中。
<input type="text" name="Name" [ngModel]="contact" /> //单向绑定
<input type="text" name="Name" [(ngModel)]="contact" /> //双向绑定
NgModel指令可以追踪表单控件的状态还能根据其状态使用对应的CSS状态类来更新表单控件的类名,绑上就可以用。
状态 true时的CSS类名 false时的CSS类名
控件被访问 ng-touched ng-untouched
控件值变了 ng-dirty ng-pristine
控件值有效 ng-valid ng-invalid
.ng-valid[required], .ng-valid.required {
border-left: 5px solid #42A948; /* green */
}
NgModelGroup指令
NgModelGroup指令可以对表单输入内容进行分组,方便我们在语义上区分不同类型的输入。下面例子就是将名字的输入表单分成一组。(需要先理解局部模版变量才好理解它的作用)
<fieldset ngModelGroup="nameGroup" #nameGroup="ngModleGroup">
<lable>名字:</lable>
<input type="text" name="name" required/>
<input... />
</fieldset>
对于表单有一个重要的ngSubmit事件,可以响应表单里类型为submit的按钮操作,并负责控制表单的提交流程。注意放的位置和局部表单变量。绑定了ngSubmit事件,提交后会先执行原生onSubmit事件再执行绑定的事件。
<form>
元素上的novalidate
属性会阻止浏览器使用原生HTML中的表单验证器。
<form #aForm="ngForm" (ngSubmit)="doSubmit(aForm.value)" novalidate>
......
......
<button type="submit" [disable]="!aForm.value">提交<buttom>
</form>
//doSubmit
export class .....
doSubmit(formValue: any) {
...//表单数据处理之类的
}
学习响应式表单指令前需要先了解几个核心表单类:
-
AbstractControl
是三个具体表单类的抽象基类。 并为它们提供了一些共同的行为和属性,其中有些是可观察对象(Observable)。 -
FormControl 用于跟踪一个单独的表单控件的值和有效性状态。它对应于一个HTML表单控件,比如输入框和下拉框。
-
FormGroup用于 跟踪一组
AbstractControl
的实例的值和有效性状态。 该组的属性中包含了它的子控件。 组件中的顶级表单就是一个FormGroup
。 -
FormArray用于跟踪
AbstractControl
实例组成的有序数组的值和有效性状态。
FormControlDirective
FormControlDirective可以将一个已有的FormControl实例绑定到一个DOM元素。
//组件
import {FormControl} from '@angular/forms';
...
export class ... {
goControl: FormControl = new FormControl();
...
}
//模板
<input type="text" [formControl]="goControl" /> //现在可以通过goControl访问该控件的状态、值什么的了
//和#goControl="ngModel"相似,但可以在组件中使用
FormGroupDirective
FormGroupDirective可以将一个已有的表单组合绑定到一个DOM元素。
//组件
import ...
import { FormControl, FormGroup } from '@angular/forms';
...
export class ... {
public bigForm = new FormGroup ({
name: new FormControl(),
password: new FormControl()
});
...
}
//模板
<form [formGroup]="bigForm " novalidate>
<input type="..." ... formControlName="name"/>
<input type="..." ... formControlName="password"/>
</form>
FormControlName指令
FormControlName指令可以将一个已有的表单控件与一个DOM元素绑定,绑定时使用该指令为表单控件指定一个别名,这一指令仅作为FormGroupDirective指令的子元素使用。就像上面一个栗子的中出现的那个FormControlName一样用就好了。
[formGroup]
formControlName
formControlName
FormGroupName指令
当一个FormGroup套另一个FormGroup时用,大概是这样
[formGroup]
formGroupName
formControlName
formControlName
formGroupName
formControlName
formControlName
FormArrayName指令
FormArray就是数组类型的FormControl
myFormArray = new FormArray([
new formControl('早上好'),
new formControl('晚上好')
])
formArrayName
[formControlName]
[formControlName]
使用FormBuilder简化构造过程
public signInForm: FormGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.createForm();
}
createForm() {
this.signInForm = this.formBuilder.group({
userName: [ '', [
Validators.required,
Validators.pattern(/^[a-zA-Z]+[a-zA-Z0-9]$/),
Validators.minLength(4),
Validators.maxLength(14)
]],
password: [ '', [
Validators.required,
Validators.minLength(4),
Validators.maxLength(25)
]]
});
}
submit(userInfo) {
...
}
//template:
<form [formGroup]="signInForm" (submit)="submit(signInForm.value)" novalidate>
<input type="text" formControlName="userName">
<input focused="true" type="password" formControlName="password">
<button type="submit" [disabled]="!signInForm.valid">登陆</button>
</form>
InternalFormsSharedModule:
InternalFormsSharedModule模块包含的指令可以分为四个部分:
第一个部分为表单元素访问器指令
这些访问器指令时Angular表单的内部指令,在应用中无须主动使用。
- DefaultValueAccessor
- NumberValueAccessor
- SelectControlValueAccessor
- SelectMultipleControlValueAccessor
- CheckboxControlValueAccessor
第二个部分为选择框选项指令
为Angular内部指令,它们动态的标记选择框的<option>选项。
- NgSelectOption
- NgSelectMultipleOption
第三部分为表单验证指令
- RequiredValidator (增加required约束)
- MinLengthValidator (增加minlength约束)
- MaxLengthValidator (增加maxlength约束)
- PatternValidator (增加Pattern正则表达式约束)
<input type="text" MinLength=10 MaxLength=20 Pattern="[0-9]" />
第四部分为控件状态指令
Angular表单的内部指令,自动根据控件是否通过验证等状态来设置元素的CSS类
- NgControlStatus
- NgControlStatusGroup