文章目录
  1. 1. Angular2表单
    1. 1.1. 模板驱动
    2. 1.2. 模型驱动
  2. 2. 结束语

因为项目原因又玩上了Angular2(v4.0+),《玩转Angular2》系列用于探索一些灵活或者新的用法。
本文简单介绍模型驱动和模板驱动的表单,以及一些表单验证。

Angular2表单


模板驱动

很多时候我们都会使用模板驱动的表单,因为很方便。
使用Angular模板语法编写模板,便是模板驱动的表单。

  1. FormModule

使用模板驱动的一些模板语法,我们需要引入FormModule:

1
import { FormsModule } from '@angular/forms';

这样,我们的<form><input>等表单元素便是Angular元素,拥有了像ngModelngSubmit等指令或属性。

  1. 模板驱动的表单

这里我们使用最简单的input,需要输入一个3-8字符的名字。Component中的js代码几乎没多少,而html模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<form class="form-horizontal" #form="ngForm" (ngSubmit)="submit()">
<div class="form-group">
<label class="col-md-2 control-label">name</label>
<div class="col-md-6">
<input class="form-control" type="text"
[(ngModel)]="model.name" name="name"
required maxlength="8" minlength="3"
#name="ngModel" />
</div>
</div>
<div class="alert alert-danger col-md-6 col-md-offset-2" *ngIf="name.errors && (name.dirty || name.touched)">
<p [hidden]="!name.errors.required">必填</p>
<p [hidden]="!name.errors.minlength">不小于3个字符</p>
<p [hidden]="!name.errors.maxlength">不大于8个字符</p>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button [disabled]="!form.valid" type="submit" class="btn btn-info">提交</button>
</div>
</div>
</form>
  • 通过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
2
3
<form class="form-horizontal" #form="ngForm" (ngSubmit)="submit()">
<button [disabled]="!form.valid" type="submit" class="btn btn-info">提交</button>
</form>

模型驱动

模型驱动表单又称为响应式表单,它将在html上的一些模板语法迁移到js中使用。
Angular的响应式表单能让实现响应式编程风格更容易,这种编程风格更倾向于在非UI的数据模型(通常接收自服务器)之间显式的管理数据流,并且用一个UI导向的表单模型来保存屏幕上HTML控件的状态和值。响应式表单可以让使用响应式编程模式、测试和校验变得更容易。

简单地说,就是模型驱动表单更加灵活,值和状态的同步更新,以及测试性较好。

  1. 异步 vs. 同步

响应式表单是同步的。模板驱动表单是异步的。

模板驱动表单会委托指令来创建它们的表单控件。
使用响应式表单,我们会在代码中创建整个表单控件树。 我们可以立即更新一个值或者深入到表单中的任意节点,因为所有的控件都始终是可用的。

  1. ReactiveFormsModule

使用模型驱动的一些模板语法,我们需要引入ReactiveFormsModule:

1
import { ReactiveFormsModule } from '@angular/forms';
  1. 基础的表单类
  • AbstractControl
    • 是三个具体表单类的抽象基类
    • 为它们提供了一些共同的行为和属性,其中有些是可观察对象(Observable)。
  • FormControl
    • 用于跟踪一个单独的表单控件的值和有效性状态
    • 它对应于一个HTML表单控件,比如输入框和下拉框
  • FormGroup
    • 用于跟踪一组AbstractControl的实例的值和有效性状态
    • 该组的属性中包含了它的子控件
    • 组件中的顶级表单就是一个FormGroup
  • FormArray
    • 用于跟踪AbstractControl实例组成的有序数组的值和有效性状态
  1. FormGroup

有多个FormControl,把它们注册进一个父FormGroup中:

1
2
3
4
reactiveForm = new FormGroup ({
name: new FormControl(),
email: new FormControl(),
});

formGroup关联到的是form元素上的FormGroup实例reactiveForm:

1
<form class="form-horizontal" [formGroup]="reactiveForm" (ngSubmit)="submit()">

formGroup是一个响应式表单的指令,它拿到一个现有FormGroup实例,并把它关联到一个HTML元素上。

  1. formControlName

有了FormGroupname输入框就需要再添加一个语法formControlName="name",以便让它关联到类中正确的FormControl上:

1
2
3
4
5
6
<div class="form-group">
<label class="col-md-2 control-label">name</label>
<div class="col-md-6">
<input class="form-control" formControlName="name" />
</div>
</div>

这个语法告诉Angular,查阅父FormGroup,然后在这个FormGroup中查阅一个名叫nameFormControl

  1. FormBuilder

FormBuilder类能通过处理控件创建的细节问题来帮我们减少重复劳动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
constructor(private fb: FormBuilder) { // 注入FormBuilder
this.createForm();
}
createForm() {
this.reactiveForm = this.fb.group({
name: ['', [
Validators.required,
Validators.minLength(3),
Validators.maxLength(8)
]
],
email: ['',
[
Validators.required,
Validators.email
]
],
});
}

FormBuilder.group是一个用来创建FormGroup的工厂方法,它接受一个对象,对象的键和值分别是FormControl的名字和它的定义。
每个FormControl的设置都是FormControl名字和数组值。第一个数组元素是控件对应的当前值,第二个值(可选)是验证器函数或者验证器函数数组。

大多数验证器函数是Angular以Validators类的静态方法的形式提供的原装验证器。

  1. valueChanges

可以通过订阅表单控件的属性之一来了解表单控件变化。
valueChanges返回一个RxJS的Observable对象。

1
2
this.reactiveForm.valueChanges
.subscribe(data => this.onValueChanged(data));

这里我们需要添加触发事件回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 定义表单错误
formErrors = {
name: ''
};
// 对表单错误做说明映射
validationMessages = {
name: {
required: '名字必填',
minlength: '名字最少3个字符',
maxlength: '名字最多8个字符'
}
};
// 表单更新触发回调
onValueChanged(data?: any) {
if (!this.reactiveForm) {
return;
}
const form = this.reactiveForm;
// 遍历表单控件名字
for (const field in this.formErrors) {
this.formErrors[field] = ''; // 清除之前的错误信息
const control = form.get(field); // 获取控件
if (control && control.dirty && !control.valid) {
// 遍历获取错误说明
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}
}

最终效果图:

image

结束语


讲到这里,我们的两种Angular表单–模型驱动和模板驱动,它们的简单使用和校验已经完成。
而需要更复杂一些的功能,像多级FormGroup、动态表单等,后面我们或许也会讲到。
此处查看项目代码
此处查看页面效果

查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢

码生艰难,写文不易,给我家猪囤点猫粮了喵~

作者:被删

出处:https://godbasin.github.io

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

文章目录
  1. 1. Angular2表单
    1. 1.1. 模板驱动
    2. 1.2. 模型驱动
  2. 2. 结束语