Reactive forms提供了一种model-driven
的方法来处理表单中会随时间变化的输入(数据),本篇中介绍着如何控制与更新一个表单、使用多个form-group、表单验证等等的基本表单操作。
Reactive forms使用了显式且不变
的方法管理表单状况,对於表单的状态的更改每次都会回传一个新的表单状态
,由於每次都会回传一个新的状态,所以他可以保持每次该改之间的model完整性,Reactive forms是围绕着observable
所建立的,表单中的输入(数值)会提供给input flow作为他的值并可以以同步的方式访问。
Reactive forms与template forms不同,Reactive forms通过对数据模型的同步访问提供了较高的可预测性
、observable operators的不变性
和可以透过observable streams观察数据的变更
。
建立Reactive forms的三个步骤:
reactive foms module
,这个module中含有使用Reactive forms的指令。FormControl instance
。使用import关键字将ReactiveFormsModule
添加到app.module中的import阵列中。
// src/app/app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
接下来透过cli建立一个 name-editor
Component,并将FormControl
class加入到Component中并将他实体化。
// src/app/name-editor/name-editor.component.ts
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms'; // import FormControl Class
@Component({
selector: 'app-name-editor',
templateUrl: './name-editor.component.html',
styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent {
name = new FormControl(''); // instance FormControl class
}
在name-editor
的templete中建立可以与表单控制元件连动的网页元件,使用formControl
绑定templete中的元件。
<!-- src/app/name-editor/name-editor.component.html -->
<label>
Name:
<input type="text" [formControl]="name">
</label>
在画面中显示出来
<!-- src/app/app.component.html -->
<app-name-editor></app-name-editor>
可以透过两种方法显示forms中的数值:
valueChange()
中的subscription()
方法监听表单中的值。value
属性。name = new FormControl('');
this.name.valueChanges.subscribe(val => console.log(val));
Value : {{name.value}}
一个表单中会包含几个相关的控制元件,Reactive forms提供两种方法可以将多个相关的控制组件分组为单个输入形式
。
透过cli建立一个新组建,使用import将FormGroup
与FormControl
加入Component中并将他们实例化。
// src/app/profile-editor/profile-editor.component.ts (form group)
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms'; //import two class
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
// instance FormGroup & FormControl
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
});
}
将firstName
与lastName
这两个相关的控制组件透过FormGroup
分组为一个群组。
可以透过嵌套FromGroups来达到将较为复杂的表单内容分割为更小的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('')
})
});
}
将原本的profileForm Group中新增了第二层的嵌套Group,将street、city、state、zip绑定为一个FormGroup,透过这样的绑定可以将原本的profileForm保持完整的前提下再新增出一个Group。
<form [formGroup]="profileForm">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<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>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>
当需要更新多个控制组件的值时,Angular提供两种方法可以改变值,一种是可以更改整组表单的方法,另一种是更改表单部分内容的方法。
setValue()
可以更新整个表单内容,他必须要遵守整个表单的结构
。patchValue()
可以替换表单内的部分内容。使用setValue()会严格检查整个表单的结构,若结构错误则会发生嵌套错误,若是使用patchValue()在这个错误上会默默地失败。
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
});
}
对於在处理多个表单的时候还是使用手动的方式创建表单控制组件实例,这样的话可能会遇到重复宣告的问题,所以可以使用FormBuilder
,它提供了用於生成控制组件的便利方法。
import { FormBuilder } from '@angular/forms';
在Component的comstructor中Inject FormBuilder service
。
constructor(private fb: FormBuilder) { }
FormBuilder提供control()
、group()
、array()
这三个方法,他们用於生成实例包括FormControl、FormGroup、FromArray。
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) { }
}
FormArray是用於管理任何数量的未命名控件的FormGroup的替代方法,可以动态的插入或删除,所以不知道子值的数量时可以使用FormArray来代替FormGroup。
import { FormArray } from '@angular/forms';
通过在数组中定义控件,可以使用从零到许多的任意数量的控件来初始化表单数组,使用FormBuilder.array()
定义阵列并使用FormBuilder.control()
初始化控件填充数组。
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('')
])
});
可以使用getter
可以轻松访问表单阵列的实例的别名。
get aliases() {
return this.profileForm.get('aliases') as FormArray;
}
还可以使用FormArray.push()
将表单数据动态的插入到现有表单中。
addAlias() {
this.aliases.push(this.fb.control(''));
}
<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中的所有表单实例,因为表单数组元素未命名,所以您将索引分配给i变量,并将其传递给每个控件以将其绑定到formControlName输入。
Class | Description |
---|---|
AbstractControl | FormControl,FormGroup和FormArray的抽象基类,它提供了常见的行为和属性。 |
FormControl | 管理单个表单空间的值和有效性的状态,他对应到HTML的表单控件<input> 或<select> |
FormGroup | 管理一组AbstractControl实例的值和有效状态,它包含他这个FormGroup的子FormControl。 |
FormArray | 管理AbstractControl实例的阵列的值有效性。 |
FormBuilder | 用於创建FormControl的方法。 |
Directive | Description |
---|---|
FormControlDirective | 将独立的FormControl实例同步到表单控件元素。 |
FormControlName | 通过名称将现有FormGroup实例中的FormControl同步到表单控件元素。 |
FormGroupDirective | 将现有的FormGroup实例同步到DOM元素。 |
FormGroupName | 将嵌套的FormGroup实例同步到DOM元素。 |
FormArrayName | 将嵌套的FormArray实例同步到DOM元素。 |
参考文献:
Angular - Reactive Forms
>>: 让WooCommerce的订单通知信里面的商品名称附带商品网址的程序码
来部落格看图文并茂文章 补觉鸣诗 时间回到我入行第二年 这时才算是正式的系统工程师并开机接触机房 最...
进入2D渲染的世界 我们在前面的章节有提到,任何Canvas的相关程序,起手式必定是先取得渲染环境,...
使用 USB 跟传统 DVD 一样可以正常安装 Windows,而且携带方便,还不需要准备光碟机。 ...
Elasticsearch 的优化技巧 系列文章索引 (1/4) - Indexing 索引效能优化...
说到广度优先搜寻我一定要现知道Queue Queue(伫列)是先进来的元素先出去(First In ...