Angular9 响应式表单
响应式表单提供了一种模型驱动的方式来处理表单输入,其中的值会随时间而变化。本文会向你展示如何创建和更新基本的表单控件,接下来还会在一个表单组中使用多个控件,验证表单的值,以及创建动态表单,也就是在运行期添加或移除控件。
先决条件
在深入了解被动表单之前,你应该对这些内容有一个基本的了解:
- TypeScript 编程。
- Angular 的应用设计基础,就像Angular Concepts 中描述的那样。
- “表单简介”中提供的表单设计概念。
响应式表单概述
响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态。对表单状态的每一次变更都会返回一个新的状态,这样可以在变化时维护模型的整体性。响应式表单是围绕 Observable 流构建的,表单的输入和值都是通过这些输入值组成的流来提供的,它可以同步访问。
响应式表单还提供了一种更直观的测试路径,因为在请求时你可以确信这些数据是一致的、可预料的。这个流的任何一个消费者都可以安全地操纵这些数据。
响应式表单与模板驱动表单有着显著的不同点。响应式表单通过对数据模型的同步访问提供了更多的可预测性,使用 Observable 的操作符提供了不可变性,并且通过 Observable 流提供了变化追踪功能。
模板驱动的表单允许你直接在模板中修改数据,但不像响应式表单那么明确,因为它们依赖嵌入到模板中的指令,并借助可变数据来异步跟踪变化。参见表单概览以了解这两种范式之间的详细比较。
添加基础表单控件
使用表单控件有三个步骤。
- 在你的应用中注册响应式表单模块。该模块声明了一些你要用在响应式表单中的指令。
- 生成一个新的
FormControl
实例,并把它保存在组件中。
- 在模板中注册这个
FormControl
。
然后,你可以把组件添加到模板中来显示表单。
下面的例子展示了如何添加一个表单控件。在这个例子中,用户在输入字段中输入自己的名字,捕获其输入值,并显示表单控件的当前值。
注册响应式表单模块
要使用响应式表单控件,就要从 @angular/forms
包中导入 ReactiveFormsModule
,并把它添加到你的 NgModule
的 imports
数组中。
Path:"src/app/app.module.ts (excerpt)" 。
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
生成一个新的 FormControl
使用 CLI 命令 ng generate
在项目中生成一个组件作为该表单控件的宿主。
ng generate component NameEditor
要注册一个表单控件,就要导入 FormControl
类并创建一个 FormControl
的新实例,将其保存为类的属性。
Path:"src/app/name-editor/name-editor.component.ts" 。
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']
})
export class NameEditorComponent {
name = new FormControl('');
}
可以用 FormControl
的构造函数设置初始值,这个例子中它是空字符串。通过在你的组件类中创建这些控件,你可以直接对表单控件的状态进行监听、修改和校验。
在模板中注册该控件
在组件类中创建了控件之后,你还要把它和模板中的一个表单控件关联起来。修改模板,为表单控件添加 formControl
绑定,formControl
是由 ReactiveFormsModule
中的 FormControlDirective
提供的。
Path:"src/app/name-editor/name-editor.component.html" 。
<label>
Name:
<input type="text" [formControl]="name">
</label>
使用这种模板绑定语法,把该表单控件注册给了模板中名为 name
的输入元素。这样,表单控件和 DOM 元素就可以互相通讯了:视图会反映模型的变化,模型也会反映视图中的变化。
显示该组件
把该组件添加到模板时,将显示指派给 name
的表单控件。
Path:"src/app/app.component.html (name editor)" 。
<app-name-editor></app-name-editor>
显示表单控件的值
你可以用下列方式显示它的值:
- 通过可观察对象
valueChanges
,你可以在模板中使用AsyncPipe
或在组件类中使用subscribe()
方法来监听表单值的变化。
- 使用
value
属性。它能让你获得当前值的一份快照。
下面的例子展示了如何在模板中使用插值显示当前值。
Path:"src/app/name-editor/name-editor.component.html (control value)" 。
<p>
Value: {{ name.value }}
</p>
一旦你修改了表单控件所关联的元素,这里显示的值也跟着变化了。
响应式表单还能通过每个实例的属性和方法提供关于特定控件的更多信息。AbstractControl
的这些属性和方法用于控制表单状态,并在处理表单校验时决定何时显示信息。
替换表单控件的值
响应式表单还有一些方法可以用编程的方式修改控件的值,它让你可以灵活的修改控件的值而不需要借助用户交互。FormControl
提供了一个 setValue()
方法,它会修改这个表单控件的值,并且验证与控件结构相对应的值的结构。比如,当从后端 API 或服务接收到了表单数据时,可以通过 setValue()
方法来把原来的值替换为新的值。
下列的例子往组件类中添加了一个方法,它使用 setValue()
方法来修改 Nancy 控件的值。
Path:"src/app/name-editor/name-editor.component.ts (update value)" 。
updateName() {
this.name.setValue('Nancy');
}
修改模板,添加一个按钮,用于模拟改名操作。在点 Update Name 按钮之前表单控件元素中输入的任何值都会回显为它的当前值。
Path:"src/app/name-editor/name-editor.component.html (update value)" 。
<p>
<button (click)="updateName()">Update Name</button>
</p>
由于表单模型是该控件的事实之源,因此当你单击该按钮时,组件中该输入框的值也变化了,覆盖掉它的当前值。
注:
- 在这个例子中,你只使用单个控件,但是当调用FormGroup
或FormArray
实例的setValue()
方法时,传入的值就必须匹配控件组或控件数组的结构才行。
把表单控件分组
表单中通常会包含几个相互关联的控件。响应式表单提供了两种把多个相关控件分组到同一个输入表单中的方法。
- 表单组定义了一个带有一组控件的表单,你可以把它们放在一起管理。表单组的基础知识将在本节中讨论。你也可以通过嵌套表单组来创建更复杂的表单。
- 表单数组定义了一个动态表单,你可以在运行时添加和删除控件。你也可以通过嵌套表单数组来创建更复杂的表单。欲知详情,参见下面的创建动态表单。
就像 FormControl
的实例能让你控制单个输入框所对应的控件一样,FormGroup
的实例也能跟踪一组 FormControl
实例(比如一个表单)的表单状态。当创建 FormGroup
时,其中的每个控件都会根据其名字进行跟踪。下面的例子展示了如何管理单个控件组中的多个 FormControl
实例。
生成一个 ProfileEditor
组件并从 @angular/forms
包中导入 FormGroup
和 FormControl
类。
ng generate component ProfileEditor
Path:"src/app/profile-editor/profile-editor.component.ts (imports)" 。
import { FormGroup, FormControl } from '@angular/forms';
要将表单组添加到此组件中,请执行以下步骤。
- 创建一个
FormGroup
实例。
- 把这个
FormGroup
模型关联到视图。
- 保存表单数据。
创建一个 FormGroup
实例
在组件类中创建一个名叫 profileForm
的属性,并设置为 FormGroup
的一个新实例。要初始化这个 FormGroup
,请为构造函数提供一个由控件组成的对象,对象中的每个名字都要和表单控件的名字一一对应。
对此个人档案表单,要添加两个 FormControl
实例,名字分别为 firstName
和 lastName
。
Path:"src/app/profile-editor/profile-editor.component.ts (form group)" 。
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']
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
});
}
现在,这些独立的表单控件被收集到了一个控件组中。这个 FormGroup
用对象的形式提供了它的模型值,这个值来自组中每个控件的值。 FormGroup
实例拥有和 FormControl
实例相同的属性(比如 value
、untouched
)和方法(比如 setValue()
)。
把这个 FormGroup
模型关联到视图。
这个表单组还能跟踪其中每个控件的状态及其变化,所以如果其中的某个控件的状态或值变化了,父控件也会发出一次新的状态变更或值变更事件。该控件组的模型来自它的所有成员。在定义了这个模型之后,你必须更新模板,来把该模型反映到视图中。
Path:"src/app/profile-editor/profile-editor.component.html (template form group)" 。
<form [formGroup]="profileForm">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
</form>
注意,就像 FormGroup
所包含的那控件一样,profileForm
这个 FormGroup
也通过 FormGroup
指令绑定到了 form
元素,在该模型和表单中的输入框之间创建了一个通讯层。 由 FormControlName
指令提供的 formControlName
属性把每个输入框和 FormGroup
中定义的表单控件绑定起来。这些表单控件会和相应的元素通讯,它们还把更改传给 FormGroup
,这个 FormGroup
是模型值的事实之源。
保存表单数据
ProfileEditor
组件从用户那里获得输入,但在真实的场景中,你可能想要先捕获表单的值,等将来在组件外部进行处理。 FormGroup
指令会监听 form
元素发出的 submit
事件,并发出一个 ngSubmit
事件,让你可以绑定一个回调函数。
把 onSubmit()
回调方法添加为 form
标签上的 ngSubmit
事件监听器。
Path:"src/app/profile-editor/profile-editor.component.html (submit event)" 。
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
ProfileEditor
组件上的 onSubmit()
方法会捕获 profileForm
的当前值。要保持该表单的封装性,就要使用 EventEmitter
向组件外部提供该表单的值。下面的例子会使用 console.warn
把这个值记录到浏览器的控制台中。
Path:"src/app/profile-editor/profile-editor.component.ts (submit method)" 。
onSubmit() {
// TODO: Use EventEmitter with form value
console.warn(this.profileForm.value);
}
form
标签所发出的 submit
事件是原生 DOM 事件,通过点击类型为 submit
的按钮可以触发本事件。这还让用户可以用回车键来提交填完的表单。
往表单的底部添加一个 button
,用于触发表单提交。
Path:"src/app/profile-editor/profile-editor.component.html (submit button)" 。
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
&上面这个代码片段中的按钮还附加了一个
disabled
绑定,用于在profileForm
无效时禁用该按钮。目前你还没有执行任何表单验证逻辑,因此该按钮始终是可用的。稍后的验证表单输入部分会讲解基础的表单验证。
显示组件
要显示包含此表单的 ProfileEditor
组件,请把它添加到组件模板中。
Path:"src/app/app.component.html (profile editor)" 。
<app-profile-editor></app-profile-editor>
ProfileEditor
让你能管理 FormGroup
中的 firstName
和 lastName
等 FormControl
实例。
创建嵌套的表单组
表单组可以同时接受单个表单控件实例和其它表单组实例作为其子控件。这可以让复杂的表单模型更容易维护,并在逻辑上把它们分组到一起。
如果要构建复杂的表单,如果能在更小的分区中管理不同类别的信息就会更容易一些。使用嵌套的 FormGroup
可以让你把大型表单组织成一些稍小的、易管理的分组。
要制作更复杂的表单,请遵循如下步骤。
创建一个嵌套的表单组。
在模板中对这个嵌套表单分组。
某些类型的信息天然就属于同一个组。比如名称和地址就是这类嵌套组的典型例子,下面的例子中就用到了它们。
创建一个嵌套组
要在 profileForm
中创建一个嵌套组,就要把一个嵌套的 address
元素添加到此表单组的实例中。
Path:"src/app/profile-editor/profile-editor.component.ts (nested form group)" 。
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']
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
}
在这个例子中,address group
把现有的 firstName
、lastName
控件和新的 street
、city
、state
和 zip
控件组合在一起。虽然 address
这个 FormGroup
是 profileForm
这个整体 FormGroup
的一个子控件,但是仍然适用同样的值和状态的变更规则。来自内嵌控件组的状态和值的变更将会冒泡到它的父控件组,以维护整体模型的一致性。
在模板中对此嵌套表单分组
在修改了组件类中的模型之后,还要修改模板,来把这个 FormGroup
实例对接到它的输入元素。
把包含 street
、city
、state
和 zip
字段的 address
表单组添加到 ProfileEditor
模板中。
Path:"src/app/profile-editor/profile-editor.component.html (template nested form group)" 。
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
ProfileEditor
表单显示为一个组,但是将来这个模型会被进一步细分,以表示逻辑分组区域。
注:
- 这里使用了 value 属性和 JsonPipe 管道在组件模板中显示了这个 FormGroup 的值。
更新部分数据模型
当修改包含多个 FormGroup
实例的值时,你可能只希望更新模型中的一部分,而不是完全替换掉。这一节会讲解该如何更新 AbstractControl
模型中的一部分。
有两种更新模型值的方式:
- 使用
setValue()
方法来为单个控件设置新值。setValue()
方法会严格遵循表单组的结构,并整体性替换控件的值。
- 使用
patchValue()
方法可以用对象中所定义的任何属性为表单模型进行替换。
setValue()
方法的严格检查可以帮助你捕获复杂表单嵌套中的错误,而 patchValue()
在遇到那些错误时可能会默默的失败。
在 ProfileEditorComponent
中,使用 updateProfile
方法传入下列数据可以更新用户的名字与街道住址。
Path:"src/app/profile-editor/profile-editor.component.ts (patch value)" 。
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
});
}
通过往模板中添加一个按钮来模拟一次更新操作,以修改用户档案。
Path:"src/app/profile-editor/profile-editor.component.html (update value)" 。
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
当点击按钮时,profileForm
模型中只有 firstName
和 street
被修改了。注意,street
是在 address
属性的对象中被修改的。这种结构是必须的,因为 patchValue()
方法要针对模型的结构进行更新。patchValue()
只会更新表单模型中所定义的那些属性。
使用 FormBuilder 服务生成控件
当需要与多个表单打交道时,手动创建多个表单控件实例会非常繁琐。FormBuilder
服务提供了一些便捷方法来生成表单控件。FormBuilder
在幕后也使用同样的方式来创建和返回这些实例,只是用起来更简单。
通过下列步骤可以利用这项服务。
导入 FormBuilder
类。
注入这个 FormBuilder
服务。
生成表单内容。
下面的例子展示了如何重构 ProfileEditor
组件,用 FormBuilder
来代替手工创建这些 FormControl
和 FormGroup
实例。
导入 FormBuilder 类
从 @angular/forms
包中导入 FormBuilder
类。
Path:"src/app/profile-editor/profile-editor.component.ts (import)" 。
import { FormBuilder } from '@angular/forms';
注入 FormBuilder 服务
FormBuilder
是一个可注入的服务提供者,它是由 ReactiveFormModule
提供的。只要把它添加到组件的构造函数中就可以注入这个依赖。
Path:"src/app/profile-editor/profile-editor.component.ts (constructor)" 。
constructor(private fb: FormBuilder) { }
生成表单控件
FormBuilder
服务有三个方法:control()
、group()
和 array()
。这些方法都是工厂方法,用于在组件类中分别生成 FormControl
、FormGroup
和 FormArray
。
用 group
方法来创建 profileForm
控件。
Path:"src/app/profile-editor/profile-editor.component.ts (form builder)" 。
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']
})
export class ProfileEditorComponent {
profileForm = this.fb.group({
firstName: [''],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
});
constructor(private fb: FormBuilder) { }
}
在上面的例子中,你可以使用 group()
方法,用和前面一样的名字来定义这些属性。这里,每个控件名对应的值都是一个数组,这个数组中的第一项是其初始值。
&你可以只使用初始值来定义控件,但是如果你的控件还需要同步或异步验证器,那就在这个数组中的第二项和第三项提供同步和异步验证器。
比较一下用表单构建器和手动创建实例这两种方式。
- Path:"src/app/profile-editor/profile-editor.component.ts (instances)" 。
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
- Path:"src/app/profile-editor/profile-editor.component.ts (form builder)" 。
profileForm = this.fb.group({
firstName: [''],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
});
验证表单输入
表单验证用于确保用户的输入是完整和正确的。本节讲解了如何把单个验证器添加到表单控件中,以及如何显示表单的整体状态。表单验证的更多知识在表单验证一章中有详细的讲解。
使用下列步骤添加表单验证。
- 在表单组件中导入一个验证器函数。
- 把这个验证器添加到表单中的相应字段。
- 添加逻辑来处理验证状态。
最常见的验证是做一个必填字段。下面的例子给出了如何在 firstName
控件中添加必填验证并显示验证结果的方法。
导入验证器函数
响应式表单包含了一组开箱即用的常用验证器函数。这些函数接收一个控件,用以验证并根据验证结果返回一个错误对象或空值。
从 @angular/forms
包中导入 Validators
类。
Path:"src/app/profile-editor/profile-editor.component.ts (import)" 。
import { Validators } from '@angular/forms';
建一个必填字段
在 ProfileEditor
组件中,把静态方法 Validators.required
设置为 firstName
控件值数组中的第二项。
Path:"src/app/profile-editor/profile-editor.component.ts (import)" 。
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
});
HTML5 有一组内置的属性,用来进行原生验证,包括 required
、minlength
、maxlength
等。虽然是可选的,不过你也可以在表单的输入元素上把它们添加为附加属性来使用它们。这里我们把 required
属性添加到 firstName
输入元素上。
Path:"src/app/profile-editor/profile-editor.component.html (required attribute)" 。
<input type="text" formControlName="firstName" required>
注:
- 这些 HTML5 验证器属性可以和 Angular 响应式表单提供的内置验证器组合使用。组合使用这两种验证器实践,可以防止在模板检查完之后表达式再次被修改导致的错误。
显示表单状态
当你往表单控件上添加了一个必填字段时,它的初始值是无效的(invalid
)。这种无效状态会传播到其父 FormGroup
元素中,也让这个 FormGroup
的状态变为无效的。你可以通过该 FormGroup
实例的 status
属性来访问其当前状态。
使用插值显示 profileForm
的当前状态。
Path:"src/app/profile-editor/profile-editor.component.html (display status)" 。
<p>
Form Status: {{ profileForm.status }}
</p>
提交按钮被禁用了,因为 firstName
控件的必填项规则导致了 profileForm
也是无效的。在你填写了 firstName
输入框之后,该表单就变成了有效的,并且提交按钮也启用了。
创建动态表单
FormArray
是 FormGroup
之外的另一个选择,用于管理任意数量的匿名控件。像 FormGroup
实例一样,你也可以往 FormArray
中动态插入和移除控件,并且 FormArray
实例的值和验证状态也是根据它的子控件计算得来的。 不过,你不需要为每个控件定义一个名字作为 key
,因此,如果你事先不知道子控件的数量,这就是一个很好的选择。
要定义一个动态表单,请执行以下步骤。
- 导入
FormArray
类。
- 定义一个
FormArray
控件。
- 使用
getter
方法访问FormArray
控件。
- 在模板中显示这个表单数组。
下面的例子展示了如何在 ProfileEditor
中管理别名数组。
导入 FormArray 类
从 @angular/form
中导入 FormArray
,以使用它的类型信息。FormBuilder
服务用于创建 FormArray
实例。
Path:"src/app/profile-editor/profile-editor.component.ts (import)" 。
import { FormArray } from '@angular/forms';
定义 FormArray 控件
你可以通过把一组(从零项到多项)控件定义在一个数组中来初始化一个 FormArray
。为 profileForm
添加一个 aliases
属性,把它定义为 FormArray
类型。
使用 FormBuilder.array()
方法来定义该数组,并用 FormBuilder.control()
方法来往该数组中添加一个初始控件。
Path:"src/app/profile-editor/profile-editor.component.ts (aliases form array)" 。
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('')
])
});
FormGroup
中的这个 aliases
控件现在管理着一个控件,将来还可以动态添加多个。
访问 FormArray 控件
相对于重复使用 profileForm.get()
方法获取每个实例的方式,getter 可以让你轻松访问表单数组各个实例中的别名。 表单数组实例用一个数组来代表未定数量的控件。通过 getter
来访问控件很方便,这种方法还能很容易地重复处理更多控件。
使用 getter
语法创建类属性 aliases
,以从父表单组中接收表示绰号的表单数组控件。
Path:"src/app/profile-editor/profile-editor.component.ts (aliases getter)" 。
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
注:
- 因为返回的控件的类型是
AbstractControl
,所以你要为该方法提供一个显式的类型声明来访问FormArray
特有的语法。
定义一个方法来把一个绰号控件动态插入到绰号 FormArray
中。用 FormArray.push()
方法把该控件添加为数组中的新条目。
Path:"src/app/profile-editor/profile-editor.component.ts (add alias)" 。
addAlias() {
this.aliases.push(this.fb.control(''));
}
在这个模板中,这些控件会被迭代,把每个控件都显示为一个独立的输入框。
在模板中显示表单数组
要想为表单模型添加 aliases
,你必须把它加入到模板中供用户输入。和 FormGroupNameDirective
提供的 formGroupName
一样,FormArrayNameDirective
也使用 formArrayName
在这个 FormArray
实例和模板之间建立绑定。
在 formGroupName
<div>
元素的结束标签下方,添加一段模板 HTML。
Path:"src/app/profile-editor/profile-editor.component.html (aliases form array template)" 。
<div formArrayName="aliases">
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
<div *ngFor="let alias of aliases.controls; let i=index">
<!-- The repeated alias template -->
<label>
Alias:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
*ngFor
指令对 aliases FormArray
提供的每个 FormControl
进行迭代。因为 FormArray
中的元素是匿名的,所以你要把索引号赋值给 i 变量,并且把它传给每个控件的 formControlName
输入属性。
每当新的 alias
加进来时,FormArray
的实例就会基于这个索引号提供它的控件。这将允许你在每次计算根控件的状态和值时跟踪每个控件。
添加一个别名
最初,表单只包含一个绰号字段,点击 Add Alias
按钮,就出现了另一个字段。你还可以验证由模板底部的“Form Value”显示出来的表单模型所报告的这个绰号数组。
注:
- 除了为每个绰号使用
FormControl
之外,你还可以改用FormGroup
来组合上一些额外字段。对其中的每个条目定义控件的过程和前面没有区别。
响应式表单 API 汇总
下列表格给出了用于创建和管理响应式表单控件的基础类和服务。
类
类 | 说明 |
---|---|
AbstractControl |
所有三种表单控件类(FormControl 、FormGroup 和 FormArray )的抽象基类。它提供了一些公共的行为和属性。 |
FormControl |
管理单体表单控件的值和有效性状态。它对应于 HTML 的表单控件,比如 <input> 或 <select> 。 |
FormGroup |
管理一组 AbstractControl 实例的值和有效性状态。该组的属性中包括了它的子控件。组件中的顶层表单就是 FormGroup 。 |
FormArray |
管理一些 AbstractControl 实例数组的值和有效性状态。 |
FormBuilder |
一个可注入的服务,提供一些用于提供创建控件实例的工厂方法。 |
指令
指令 | 说明 |
---|---|
FormControlDirective |
把一个独立的 FormControl 实例绑定到表单控件元素。 |
FormControlName |
把一个现有 FormGroup 中的 FormControl 实例根据名字绑定到表单控件元素。 |
FormGroupDirective |
把一个现有的 FormGroup 实例绑定到 DOM 元素。 |
FormGroupName |
把一个内嵌的 FormGroup 实例绑定到一个 DOM 元素。 |
FormArrayName |
把一个内嵌的 FormArray 实例绑定到一个 DOM 元素。 |
更多建议: