玩转Angular2(6)--模型驱动和模板驱动的表单
更新日期:
因为项目原因又玩上了Angular2(v4.0+),《玩转Angular2》系列用于探索一些灵活或者新的用法。
本文简单介绍模型驱动和模板驱动的表单,以及一些表单验证。
Angular2表单
模板驱动
很多时候我们都会使用模板驱动的表单,因为很方便。
使用Angular模板语法编写模板,便是模板驱动的表单。
- FormModule
使用模板驱动的一些模板语法,我们需要引入FormModule
:
1 | import { FormsModule } from '@angular/forms'; |
这样,我们的<form>
和<input>
等表单元素便是Angular元素,拥有了像ngModel
、ngSubmit
等指令或属性。
- 模板驱动的表单
这里我们使用最简单的input
,需要输入一个3-8字符的名字。Component中的js代码几乎没多少,而html模板如下:
1 | <form class="form-horizontal" #form="ngForm" (ngSubmit)="submit()"> |
- 通过
ngModel
跟踪修改状态与有效性验证
在表单中使用ngModel
可以获得比仅使用双向数据绑定更多的控制权,不仅仅跟踪状态。它还使用特定的Angular CSS类来更新控件,以反映当前状态。
可以利用这些CSS类来修改控件的外观,显示或隐藏消息。
required
/maxlength
/minlength
: 用于表单校验name.touched
: 控件被访问过name.dirty
: 控件的值变化了name.errors
: 控件校验错误
指向input
控件的引用变量上的valid
属性,可用于检查控件是否有效、是否显示/隐藏错误信息。
#name="ngModel"
#name
是模板引用变量。使用井号(#
)来声明引用变量。
模板引用变量通常用来引用模板中的某个DOM元素,它还可以引用Angular组件或指令或Web Component。
指令的exportAs
属性告诉Angular如何链接模板引用变量到指令。
这里把name
设置为ngModel
是因为ngModel
指令的exportAs
属性设置成了”ngModel”。name
属性的用途是有效性验证和对表单元素的变更进行追踪。
- 使用
ngSubmit
提交该表单
按钮位于表单的底部,它自己不做任何事,但因为有type="submit"
,所以会触发表单提交。
而要使得表单提交生效,需要把该表单的ngSubmit
事件属性绑定到对应的提交事件。
如果需要校验,则需要添加#form="ngForm"
,将form
变量exportAs
属性设置成ngForm
,可跟踪表单有效性验证:
1 | <form class="form-horizontal" #form="ngForm" (ngSubmit)="submit()"> |
模型驱动
模型驱动表单又称为响应式表单,它将在html上的一些模板语法迁移到js中使用。
Angular的响应式表单能让实现响应式编程风格更容易,这种编程风格更倾向于在非UI的数据模型(通常接收自服务器)之间显式的管理数据流,并且用一个UI导向的表单模型来保存屏幕上HTML控件的状态和值。响应式表单可以让使用响应式编程模式、测试和校验变得更容易。
简单地说,就是模型驱动表单更加灵活,值和状态的同步更新,以及测试性较好。
- 异步 vs. 同步
响应式表单是同步的。模板驱动表单是异步的。
模板驱动表单会委托指令来创建它们的表单控件。
使用响应式表单,我们会在代码中创建整个表单控件树。 我们可以立即更新一个值或者深入到表单中的任意节点,因为所有的控件都始终是可用的。
- ReactiveFormsModule
使用模型驱动的一些模板语法,我们需要引入ReactiveFormsModule
:
1 | import { ReactiveFormsModule } from '@angular/forms'; |
- 基础的表单类
AbstractControl
- 是三个具体表单类的抽象基类
- 为它们提供了一些共同的行为和属性,其中有些是可观察对象(
Observable
)。
FormControl
- 用于跟踪一个单独的表单控件的值和有效性状态
- 它对应于一个HTML表单控件,比如输入框和下拉框
FormGroup
- 用于跟踪一组
AbstractControl
的实例的值和有效性状态 - 该组的属性中包含了它的子控件
- 组件中的顶级表单就是一个
FormGroup
- 用于跟踪一组
FormArray
- 用于跟踪
AbstractControl
实例组成的有序数组的值和有效性状态
- 用于跟踪
FormGroup
有多个FormControl
,把它们注册进一个父FormGroup
中:
1 | reactiveForm = new FormGroup ({ |
将formGroup
关联到的是form
元素上的FormGroup
实例reactiveForm:
1 | <form class="form-horizontal" [formGroup]="reactiveForm" (ngSubmit)="submit()"> |
formGroup
是一个响应式表单的指令,它拿到一个现有FormGroup
实例,并把它关联到一个HTML元素上。
- formControlName
有了FormGroup
,name
输入框就需要再添加一个语法formControlName="name"
,以便让它关联到类中正确的FormControl
上:
1 | <div class="form-group"> |
这个语法告诉Angular,查阅父FormGroup
,然后在这个FormGroup
中查阅一个名叫name
的FormControl
。
- FormBuilder
FormBuilder
类能通过处理控件创建的细节问题来帮我们减少重复劳动。
1 | constructor(private fb: FormBuilder) { // 注入FormBuilder |
FormBuilder.group
是一个用来创建FormGroup
的工厂方法,它接受一个对象,对象的键和值分别是FormControl
的名字和它的定义。
每个FormControl
的设置都是FormControl
名字和数组值。第一个数组元素是控件对应的当前值,第二个值(可选)是验证器函数或者验证器函数数组。
大多数验证器函数是Angular以Validators
类的静态方法的形式提供的原装验证器。
- valueChanges
可以通过订阅表单控件的属性之一来了解表单控件变化。valueChanges
返回一个RxJS的Observable对象。
1 | this.reactiveForm.valueChanges |
这里我们需要添加触发事件回调:
1 | // 定义表单错误 |
最终效果图:
结束语
讲到这里,我们的两种Angular表单–模型驱动和模板驱动,它们的简单使用和校验已经完成。
而需要更复杂一些的功能,像多级FormGroup
、动态表单等,后面我们或许也会讲到。
此处查看项目代码
此处查看页面效果
码生艰难,写文不易,给我家猪囤点猫粮了喵~
查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢
如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢