Angular表单中的FormControl、FormGroup、FormBuilder、FormArray


要使用响应式表单,首先需要在@angular/forms包中导入ReactiveFormsModule,并把它放到ngModule的imports数组中去。

login.module.ts

import { ReactiveFormsModule } from '@angular/forms';@NgModule({imports: [ReactiveFormsModule,    //<==CommonModule],...
})

1 FormControl

FormControl是为单个表单控件提供支持的类,它是Angular表单中的最基本的构造块

FormControl封装了这些字段的值和状态,比如是否有效、是否脏(被修改过)或是否有错误等。还提供了一系列公共API。

1.1 构造函数

创建新的FormControl示例。

constructor(formState: any = null, validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[])
参数 数据类型 说明
formState any 使用一个初始值或定义了初始值和禁用状态的对象初始化该控件。可选,默认值为null
validatorOrOpts ValidatorFn或AbstractControlOptions或ValidatorFn[] 一个同步验证器函数或其数组,或者一个包含验证函数和验证触发器的AbstractControlOptions对象。可选,默认值为undefined
asyncValidator AsyncValidatorFn或AsyncValidatorFn[] 一个异步验证器函数或其数组。可选,默认值为undefined

具体示例如下。

1.1.1 用一个初始值初始化FormControl

const control = new FormControl('somevalue');
console.log(control.value); //'some value'

1.1.2 用一个表单状态对象初始化控件

这里用到的是value和disabled键

const control = new FormControl({value:'n/a',disabled:true});
console.log(control.value); //'n/a'
console.log(control.status); //'DISABLED'

具体使用示例如下。

login.component.html

<div><label>Name:</label><input type="text" [formControl]="username">
</div>
<div><label>Password:</label><input type="password" [formControl]="password">
</div>
<button type="submit" (click)="onSubmit()">登录</button>

login.conponent.ts

import { FormControl } from '@angular/forms';
import { Component } from '@angular/core';@Component({selector: 'app-login',templateUrl: './login.component.html',styleUrls: ['./login.component.css']
})
export class LoginComponent {username:FormControl = new FormControl('Tom');password:FormControl = new FormControl();onSubmit() {console.log(this.username.value, this.password.value);}
}
  • formControl是一个指令,它接收一个FormControl的实例,来管理表单元素。
  • 构造FormControl的实例时,第一个参数是表单元素的初始值,也可传入一个对象{value:‘Tom’,disabled:true},里面可以包含表单元素的状态,如是否禁用等。
  • 在提交时,可以通过this.name.value获取表单元素的值。
  • 当我们需要在元素值改变时做一些事情,可以订阅对应控件的valueChanges事件。
this.name.valueChanges.subscribe(() => {// do something...console.log(this.name);
});

1.1.3 用一个同步验证器初始化控件

const control = new FormControl('',Validators.required);
console.log(control.value); //''
console.log(control.status); //'INVALID'

具体使用示例如下。
password.validator.ts

export const PasswordValidator = (password?:RegExp): ValidatorFn => {return (control:AbstractControl): {[key: string]: any}  => {let error = null;if (password && !password.test(control.value)) {error = {password:control.value}}return error;}
}

login.component.html

<div><label>Password:</label><input type="password" [formControl]="password"><div [style.color]="'red'" *ngIf="password.invalid && (password.touched || password.dirty)"><p *ngIf="password.errors.required">password can not be empty!</p><p *ngIf="password.errors.password">password is illegal!</p></div>
</div>

login.component.ts

password:FormControl = new FormControl('', [Validators.required, PasswordValidator()]);
  • FormControl的第二个参数可以传入一个ValidatorFn对象或者一个包含ValidatorFn对象的数组。
  • angular2内置的验证器可以通过Validators取到,如:Validators.required。
  • 自定义的验证器只需引用我们在模板驱动型表单中构造的验证器工厂函数(PasswordValidator)生成一个ValidatorFn对象的实例即可。
  • FormControl上包含了表单的验证信息,在模板中可以直接使用它。

1.1.4 用一个配置对象初始化控件

const control = new FormControl('',{validators:Validators.required,
asyncValidators:myAsyncValidator
});

给FormControl添加异步验证器的具体示例如下。

username.validator.ts

const usernameList = ['jack','rose','amy','tom'
];export const checkNameValidator = () => {return (control:AbstractControl) => new Promise((resolve, reject) => {setTimeout(() => {if (usernameList.indexOf(control.value) >= 0) {resolve({'checkName':control.value});} else {resolve(null);}}, 2000)});
}

login.component.html

<label>Name:</label><input type="text" [formControl]="username"><div [style.color]="'red'" *ngIf="username.invalid && (username.touched || username.dirty)"><p *ngIf="username.errors.required">UserName can not be empty!</p><p *ngIf="username.errors.checkName">UserName is exist!</p></div>

login.component.ts

username:FormControl = new FormControl('jack', Validators.required, checkNameValidator());
  • FormControl的第三个参数可以传入一个AsyncValidatorFn对象或者一个包含AsyncValidatorFn对象的数组。
  • 异步验证器只需引用我们在模板驱动型表单中构造的验证器工厂函数(checkNameValidator )生成一个AsyncValidatorFn对象的实例即可。

1.1.5 配置该控件,使其在blur事件时更新

把updateOn选项设置为’blur’,可以在发生blur事件时更新。

const control = new FormControl('',{updateOn:'blur'});

1.1.6 配置该控件,使其在发生submit事件时更新

把updateOn选项设置为’submit’,可以在发生submit事件时更新

const control = new FormControl('',{updateOn:'submit'});

1.2 方法

1.2.1 setvalue()

设置该表单控件的新值

setValue(value: any, options: { onlySelf?: boolean; emitEvent?: boolean; emitModelToViewChange?: boolean; emitViewToModelChange?: boolean; } = {}): void
参数 数据类型 说明
value any 控件的新值
options object 当值发生变化时,该配置项决定如何传播变更以及发出事件。该配置项会传递给updateVauleAndValidity方法。可选,默认值是{}

options中具体的属性有:

  • onlySelf:如果为true,则每次变更只影响该控件本身,不影响其父控件。默认为false。
  • emitEvent:如果为true或未提供(默认),则当控件值变化时,statusChanges和valueChanges这两个Observable都会以最近的状态和值发出事件。如果为false,则不会发出事件。
  • emitModelToViewChange:如果为true或未提供(默认),则每次都会触发一个onChange事件以更新视图。
  • emitViewToModelChange:如果为true或未提供(默认),则每次变化都会触发一个ngModelChange事件以更新模型。

1.2.2 patchValue()

修补控件的值。在FormControl这个层次上,该函数的功能和setValue完全相同。但在FormGroup和FormArray上的patchValue则有不同的行为。

patchValue(value: any, options: { onlySelf?: boolean; emitEvent?: boolean; emitModelToViewChange?: boolean; emitViewToModelChange?: boolean; } = {}): void
参数 数据类型 说明
value any
options object 可选,默认值是{}

1.2.3 reset()

重置该表单控件,把它标记为pristine和untouched,并把它的值设置为null。

reset(formState: any = null, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
formState any 使用初始值或一个包含初始值和禁用状态的对象来重置该组件。可选,默认值是null
options object 当值发生变化时,该配置项会决定控件如何传播变更以及发出事件。可选,默认值是{}

options中具体的属性有:

  • onlySelf:如果为true,则每次变更只影响该控件本身,不影响其父控件。默认为false。
  • emitEvent:如果为true或未提供(默认),则当控件值变化时,statusChanges和valueChanges这两个Observable都会以最近的状态和值发出事件。如果为false,则不会发出事件。

1.2.3.1 把控件重置为初始值

通过传递包含值和禁用状态的独立值或表单状态对象,可以将其重置为特定的表单状态(这是所支持的禁用的两个非计算状态)。

const control = new FormControl('Nancy');
console.log(control.value); //'Nancy'
control.reset('Drew');
console.log(control.value); //'Drew'

1.2.3.2 把控件重置回初始值并禁用

const control = new FormControl('Nancy');
console.log(control.value); //'Nancy'
console.log(control.status); //'VALID'control.reset({value:'Drew',disabled:true});
console.log(control.value); //'Drew'
console.log(control.status); //'DISABLED'

1.2.4 registerOnChange()

注册变更事件的监听器

registerOnChange(fn: Function): void
参数 数据类型 说明
fn Function 当值变化时,就会调用该方法

1.2.5 registerOnDisabledChange()

注册禁用事件的监听器

registerOnDisabledChange(fn: (isDisabled: boolean) => void): void
参数 数据类型 说明
fn (isDisabled: boolean) => void 当禁用状态发生变化时,就会调用该方法

2 FormGroup

FormGroup中包含一组FormControl实例,用来管理多个FormControl。它将每个子FormControl的值聚合进一个对象,它的key是每个控件的名字,可以跟踪FormControl组的值和验证状态。FormGroup的状态是归集的所有子控件的状态值计算出来的。

2.1 构造函数

创建一个新的FormGroup实例。

constructor(controls: { [key: string]: AbstractControl; }, validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[])
参数 数据类型 说明
controls object 一组子控件。每个子控件的名字就是它注册时用的key
validatorOrOpts ValidatorFn或AbstractControlOptions或ValidatorFn[] 一个同步验证器函数或其数组,或者一个包含验证函数和验证触发器的AbstractControlOptions对象。可选,默认值是undefined
asyncValidator AsyncValidatorFn或AsyncValidatorFn[] 单个的异步验证器函数或其数组。可选,默认值是undefined

2.1.1 创建一个带有两个控件的表单组

const form = new FormGroup({first:new FormControl('Nancy',Validators.minLength(2),last:new FormControl('Drew')),
});console.log(form.value); //{first:'Nancy',last:'Drew'}
console.log(form.status); //'VALID'

2.1.2 创建一个具有组级验证器的表单组

当你要根据一个以上子控件的值来决定有效性时,可用第二个参数传入一些组级验证器或用第三个参数传入一些组级异步验证器。

const form = new FormGroup({password: new FormControl('', Validators.minLength(2)),passwordConfirm: new FormControl('', Validators.minLength(2)),
}, passwordMatchValidator);function passwordMatchValidator(g: FormGroup) {return g.get('password').value === g.get('passwordConfirm').value? null : {'mismatch': true};
}

像FormControl实例一样,你也可以在配置对象中传入验证器和异步验证器。

const form = new FormGroup({password: new FormControl('')passwordConfirm: new FormControl('')
}, { validators: passwordMatchValidator, asyncValidators: otherValidator });

2.1.3 为表单组中的所有空间设置updateOn属性

该选项对象可用来为每个子控件的updateOn属性设置默认值。如果在组级把updateOn设置为’blur’,则所有子控件的默认值也是’blur’,除非这个子控件显式的指令了另一个updateOn值。

const c = new FormGroup({one:new FromControl()},{updateOn:'blur'});

2.2 属性

属性 说明
controls: {[key: string]: AbstractControl;} 一组子控件。每个子控件的名字就是它注册时用的key

2.3 方法

2.3.1 registerControl()

向组内的控件列表中注册一个控件,该方法不会更新控件的值或其有效性。

registerControl(name: string, control: AbstractControl): AbstractControl
参数 数据类型 说明
name string 注册到集合中的控件名
control AbstractControl 提供这个名字对应的控件

2.3.2 addControl()

往组内添加一个控件,该方法还会更新控件内值和有效性

addControl(name: string, control: AbstractControl): void
参数 数据类型 说明
name string 注册到集合中的控件名
control AbstractControl 提供这个名字对应的控件

2.3.3 removeControl()

从该组中移除一个控件

removeControl(name: string): void
参数 数据类型 说明
name string 要从集合中移除的控件名

2.3.4 setControl()

替换现有控件

setControl(name: string, control: AbstractControl): void
参数 数据类型 说明
name string 要从集合中替换掉的控件名
control AbstractControl 提供具有指定名称的控件

2.3.5 contains()

检查组内是否具有一个指定名字的已启用的控件。对于已禁用的控件返回false,否则返回true。如果你只想检查它是否存在于该组中,请改用get代替。

contains(controlName: string): boolean
参数 数据类型 说明
controlName string 要在集合中检查是否存在的控件名

2.3.6 setValue()

设置此FormGroup的值。它接受一个与组结构对应的对象,以控件名作为key。它会进行严格的检查,当设置了不存在或被排出去的控件的值时会失败。

setValue(value: { [key: string]: any; }, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value object 控件的新值,其结构必须和该组的结构相匹配
options object 当值变化时,此配置项会决定该控件会如何让传播变更以及发出时间。该配置项会被传给updateValueAndValidity方法。可选,默认值是{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

设置表单的完整值

const form = new FormGroup({first:new FormControl(),last:new FormControl()
});console.log(form.value); //{first:null,last:null}form.setValue({first:'Nancy',last:'Drew'});
console.log(form.value); //{first:'Nancy',last:'Drew'}

2.3.7 patchValue()

修补此FormGroup的值。它接受一个以控件名为key的对象,并尽量把它们的值匹配到组中正确的控件上,它只会替换表单模型中修改过的那些属性。它能接受组的超集和子集而不会抛出错误。

patchValue(value: { [key: string]: any; }, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value object 与该组的结构匹配的对象
options object 在修补了该值之后,此配置项会决定控件如何传播变更以及发出事件。该配置项会被传给updateValueAndValidity方法。可选,默认值为{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

修补表单组的值

const form = new FormGroup({first:new FormControl(),last:new FormControl()
});console.log(form.value); //{first:null,last:null}form.setValue({first:'Nancy'});
console.log(form.value); //{first:'Nancy',last:null}

2.3.8 reset()

重置这个FormGroup,把它的各级子控件都标记为pristine和untouched,并把它们的值都设置为null。
也可以传入一个与表单结构相匹配的以控件名为key的Map,来把表单重置为特定的状态。其状态可以是一个单独的值,也可以是一个同时具有值和禁用状态的表单状态对象。

reset(value: any = {}, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value any 使用一个初始值或包含初始值与禁用状态的对象重置该控件。可选,默认值是{}
options object 当该组被重置时,此配置项会决定控件如何传播变更以及发出事件。该配置项会被传给updateValueAndValidity方法。可选,默认值为{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

重置该表单组的值

const form = new FormGroup({first:new FormControl('first name'),last:new FormControl('last name')
});console.log(form.value); //{first:'first name',last:'last name'}form.reset({first:'name',last:'last name'});
console.log(form.value); //{first:'name',last:'last name'}

重置该表单组的值以及禁用状态

const form = new FormGroup({first:new FormControl('first name'),last:new FormControl('last name')
});console.log(form.value); //{first:'first name',last:'last name'}form.reset({first:{value:'name',disabled:true},last:'last'});
console.log(form.value); //{first:'name',last:'last name'}
//代码示例来自官方文档,此处不清楚为何未重置成功,可能是两个表单状态格式要书写一致console.log(this.form.get('first'.status)); //'DISABLED'

2.3.9 getRawValue()

这个FormGroup的聚合值,包括所有已禁用的控件。获取所有控件的值而不管其禁用状态。用value属性获取组中的值时,会从FormGroup中排除所有已禁用的控件。

getRawValue(): any[]

2.4 具体使用示例

login-component.html

<div [formGroup]="info"><div><label>Name:</label><input type="text" formControlName="username"><div [style.color]="'red'" *ngIf="info.get('username').invalid && (info.get('username').touched || info.get('username').dirty)"><p *ngIf="info.get('username').errors.required">UserName can not be empty!</p><p *ngIf="info.get('username').errors.checkName">UserName is exist!</p></div></div><div><label>Password:</label><input type="password" formControlName="password"><div [style.color]="'red'" *ngIf="info.get('password').invalid && (info.get('password').touched || info.get('password').dirty)"><p *ngIf="info.get('password').errors.required">password can not be empty!</p><p *ngIf="info.get('password').errors.password">password is illegal!</p></div></div><button type="submit" (click)="onSubmit()">Submit</button>
</div>

login.component.ts

import { checkNameValidator } from '../validators/username.validator';
import { PasswordValidator } from '../validators/password.validator';
import { FormControl, FormGroup, Validator, Validators } from '@angular/forms';
import { Component } from '@angular/core';@Component({selector: 'app-login',templateUrl: './login.component.html',styleUrls: ['./login.component.css']
})
export class LoginComponent {info:FormGroup = new FormGroup({username:new FormControl('jack', Validators.required, checkNameValidator()),password:new FormControl('', [Validators.required, PasswordValidator()])});onSubmit() {console.log(this.info.value);}
}
  • 构造FormGroup需传入一个包含有FormControl实例的对象。
  • 在模板中可以通过[formGroup]="info"指令,管理一个表单组。
  • 在包含有formGroup指令的元素的子节点上,可以使用formControlName="name"代替[formControl]="name"来控制表单元素,formControlName指令只能在formGroup指令内部使用。
  • 在FormGroup上可以通过info.get(‘name’)获取FormControl实例。
  • 在FormGroup上可以通过this.info.value获取表单组的值。
  • 在FormGroup上可以通过this.info.setValue(newValue)或this.info.patchValue(newValue)设置FormGroup的值,setValue是修改整个FormGroup的值,传入的值必须包含全部的属性,缺少任意一个属性控制台会报错,用patchValue时,可修改部分属性的值。
  • FormGroup内部可以嵌套FormGroup,如Name可能又包含firstName和lastName,此时我们可以构造嵌套的FormGroup。
<div formGroupName="name"><input type="text" formControlName="first"><input type="text" formControlName="last">
</div>
info:FormGroup = new FormGroup({name: new FormGroup({first:new FormControl(),last:new FormControl()})
});

3 FormArray

跟踪每一个控件数组的值和有效特性,控件可以是FormControl、FormGroup或FormArray的实例。它聚合了数组中每个表单控件的值,还会根据其所有子控件的状态总结出自己的状态。

3.1 构造函数

创建一个新的 FormArray 实例

constructor(controls: AbstractControl[], validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[])
参数 数据类型 说明
controls AbstractControl[] 一个子控件数组。在注册后,每个子控件都会有一个指定的索引。
validatorOrOpts ValidatorFn或AbstractControlOptions或ValidatorFn[] 一个同步验证器函数或其数组,或者一个包含验证函数和验证触发器的 AbstractControlOptions 对象。可选, 默认值是 undefined
asyncValidator AsyncValidatorFn或AsyncValidatorFn[] 单个的异步验证器函数或其数组。可选,默认值是 undefined

3.1.1创建表单控件的数组

const arr = new FormArray([new FormControl('Nancy', Validators.minLength(2)),new FormControl('Drew'),
]);console.log(arr.value); //['Nancy', 'Drew']
console.log(arr.status); //'VALID'

3.1.2 创建一个带有数组级验证器的表单数组

你可以定义数组级的验证器和异步验证器。当你需要根据一个或多个子控件的值来进行有效性验证时,这很有用。

这两种类型的验证器分别通过第二个和第三个参数或作为配置对象的一部分传进去。

const arr = new FormArray([new FormControl('Nancy'),new FormControl('Drew')
], {validators: myValidator, asyncValidators: myAsyncValidator});

3.1.3 为表单数组中的所有控件设置 updateOn 属性

该配置对象可以为每个子控件的updateOn属性设置默认值。如果在数组级把 updateOn 设置为’blur’,则所有子控件的默认值也是’blur’,除非这个子控件显式的指定了另一个 updateOn 值。

const arr = new FormArray([new FormControl()
], {updateOn: 'blur'});

3.1.4 从表单数组中添加或删除控件

要改变数组中的控件列表,可以使用FormArray本身的push、insert、removeAt 或 clear方法。这些方法能确保表单数组正确的跟踪这些子控件。不要直接修改实例化 FormArray 时传入的那个 AbstractControl 数组,否则会导致奇怪的、非预期的行为,比如破坏变更检测机制。

3.2 属性

属性 数据类型 说明
controls AbstractControl[] 一个子控件数组。在注册后,每个子控件都会有一个指定的索引。
length number 控件数组的长度。

3.3 方法

3.3.1 at()

获取数组中指定index处的AbstractControl。

at(index: number): AbstractControl
参数 数据类型 说明
index number 要获取的控件在数组中的索引

3.3.2 push()

在数组的末尾插入一个新的 AbstractControl。

push(control: AbstractControl): void
参数 数据类型 说明
control AbstractControl 要插入的表单控件

3.3.3 insert()

在数组中的指定index处插入一个新的 AbstractControl。

insert(index: number, control: AbstractControl): void
参数 数据类型 说明
index number 要插入该控件的索引序号
control AbstractControl 要插入的表单控件

3.3.4 removeAt()

移除数组中指定index处的AbstractControl。

removeAt(index: number): AbstractControl
参数 数据类型 说明
index number 要移除的控件在数组中的索引

3.3.5 setControl()

在数组中的指定index处将现有的控件替换成一个新的AbstractControl。

setControl(index: number, control: AbstractControl): void
参数 数据类型 说明
index number 要替换的控件在数组中的索引
control AbstractControl 要用来替换现有控件的控件

3.3.6 setValue()

设置此FormArray的值。它接受一个与组结构对应的对象,以控件名作为key。它会进行严格的检查,当设置了不存在或被排出去的控件的值时会失败。

setValue(value: any[], options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value any[] 要传给这些控件的值的数组
options object 当值变化时,此配置项会决定该控件会如何让传播变更以及发出时间。该配置项会被传给updateValueAndValidity方法。可选,默认值是{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

设置表单的完整值

const arr = new FormArray({new FormControl(),new FormControl()
});console.log(arr.value); //[null,null]arr.setValue(['Nancy','Drew']);
console.log(form.value); //['Nancy','Drew']

3.3.7 patchValue()

修补此FormArray的值。它接受一个以控件名为key的对象,并尽量把它们的值匹配到组中正确的控件上,它只会替换表单模型中修改过的那些属性。它能接受组的超集和子集而不会抛出错误。

patchValue(value: any[], options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value any[] 由各个控件的值组成的数组
options object 在修补了该值之后,此配置项会决定控件如何传播变更以及发出事件。该配置项会被传给updateValueAndValidity方法。可选,默认值为{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

修补表单组中各个控件的值

const arr = new FormArray({new FormControl(),new FormControl()
});console.log(arr.value); //[null,null]arr.patchValue(['Nancy']);
console.log(form.value); //['Nancy',null]

3.3.8 reset()

重置这个FormArray,把它的各级子控件都标记为pristine和untouched,并把它们的值都设置为null。
也可以传入一个与表单结构相匹配的状态数组,来把表单重置为特定的状态。每个状态可以是一个单独的值,也可以是一个同时具有值和禁用状态的表单状态对象。

reset(value: any = {}, options: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
参数 数据类型 说明
value any 各控件值的数组。可选,默认值是[]
options object 当该组被重置时,此配置项会决定控件如何传播变更以及发出事件。该配置项会被传给updateValueAndValidity方法。可选,默认值为{}

options的具体参数为:

  • onlySelf:如果为true,则每个变更仅仅影响当前控件,而不会影响父控件。默认为false。
  • emitEvent:如果为true会未提供(默认),则当控件值发生变化时,statusChanges和valueChanges这两个Observable分别会以最近的状态和值发出事件。如果为false则不发出事件。

重置该表单组的值

const arr = new FormArray({new FormControl(),new FormControl()
});arr.reset(['name','last name']);
console.log(form.value); //['name','last name']

重置表单数组中的各个值和第一个控件的禁用状态

this.arr.reset([{value: 'name', disabled: true},'last'
]);console.log(this.arr.value);  // ['name', 'last name']
//代码示例来自官方文档,此处不清楚为何未重置成功,可能是两个表单状态格式要书写一致console.log(this.arr.get('first'.status)); //'DISABLED'

3.3.9 getRawValue()

这个FormArray的聚合值,包括所有已禁用的控件。获取所有控件的值而不管其禁用状态。用value属性获取组中的值时,会从FormGroup中排除所有已禁用的控件。

getRawValue(): any[]

3.3.10 clear()

移除FormArray中所有的控件

gclear(): void

移除表单组中所有元素

const arr = new FormArray([new FormControl(),new FormControl()
]);
console.log(arr.length);  // 2arr.clear();
console.log(arr.length);  // 0

相比一个一个删除元素,这是一种更简单更有效的替代方法

const arr = new FormArray([new FormControl(),new FormControl()
]);while (arr.length) {arr.removeAt(0);
}

3.4 具体示例

address.component.html

<div [formGroup]="info"><div><div>Address</div><div><button (click)="addAddress()">Add</button></div><div *ngFor="let address of info.get('address').controls;let index=index"><p>Provience:<input [formControl]="address.get('provience')">City:<input [formControl]="address.get('city')"><button (click)="removeAddress(index)">Remove</button></p></div></div>
</div>
<button (click)="getInfo()">Get Info</button>

address.component.ts

import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { Component, OnInit } from '@angular/core';@Component({selector: 'app-address',templateUrl: './address.component.html',styleUrls: ['./address.component.css']
})
export class AddressComponent{address:FormArray;info:FormGroup;constructor(private fb:FormBuilder) {this.createForm();}//初始化表单createForm() {this.address = this.fb.array([]);this.info = this.fb.group({address:this.address});}//添加地址addAddress() {this.address.push(new FormGroup({provience:new FormControl(),city:new FormControl()}));}//移除地址removeAddress(index) {this.address.removeAt(index);}//获取表单值getInfo() {console.log(this.info.value);}
}

4 FormBuilder

使用用户指定的配置创建AbstractControl。它提供了一个语法糖,用来简化FormControl、FormGroup 或 FormArray 实例的创建过程。它会减少构建复杂表单时所需的样板代码的数量。

4.1 方法

4.1.1 group()

构建一个新的FormGroup实例。

group(controlsConfig: { [key: string]: any; }, options: AbstractControlOptions | { [key: string]: any; } = null): FormGroup
参数 数据类型 说明
controlsConfig object 一组子控件。每个 key 就是注册进来的控件的名字。
options AbstractControlOptions或{ [key: string]: any; } FormGroup 的配置项对象。可选,默认值为null

FormGroup 的配置项对象有两种形态。
(1) AbstractControlOptions对象(首选),它包括如下属性:

  • validators:一个同步验证器函数或其数组
  • asyncValidators:一个异步验证器函数或其数组
  • updateOn:当发生哪个事件时该控件要被更新(选项)‘change’ | ‘blur’ | submit’

(2) 传统的配置对象,它包括如下属性:

  • validator:一个同步验证器函数或其数组
  • asyncValidator:一个异步验证器函数或其数组

4.1.2 control()

构建一个新的FormControl实例。

control(formState: any, validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]): FormControl
参数 数据类型 说明
formState any 使用一个初始值或定义了初始值和禁用状态的对象初始化该控件。可选,默认值为null
validatorOrOpts ValidatorFn或AbstractControlOptions或ValidatorFn[] 一个同步验证器函数或其数组,或者一个包含验证函数和验证触发器的AbstractControlOptions对象。可选,默认值为undefined
asyncValidator AsyncValidatorFn或AsyncValidatorFn[] 一个异步验证器函数或其数组。可选,默认值为undefined

*把控件初始化为禁用状态

import {Component, Inject} from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
/* . . . */
@Component({selector: 'app-disabled-form-control',template: `<input [formControl]="control" placeholder="First">`
})
export class DisabledFormControlComponent {control: FormControl;constructor(private fb: FormBuilder) {this.control = fb.control({value: 'my val', disabled: true});}
}

4.1.3 array()

构建一个新的FormArray实例。

control(formState: any, validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]): FormControl
参数 数据类型 说明
controlsConfig any[] 一个子控件数组。每个子控件的 key 都是它在数组中的索引
validatorOrOpts ValidatorFn或AbstractControlOptions或ValidatorFn[] 一个同步验证器函数或其数组,或者一个包含验证函数和验证触发器的AbstractControlOptions对象。可选,默认值为undefined
asyncValidator AsyncValidatorFn或AsyncValidatorFn[] 一个异步验证器函数或其数组。可选,默认值为undefined

4.2 具体示例

login.component.ts

import { checkNameValidator } from '../validators/name.validator';
import { PasswordValidator } from '../validators/password.validator';
import { FormBuilder, FormControl, FormGroup, Validator, Validators } from '@angular/forms';
import { Component } from '@angular/core';@Component({selector: 'app-login',templateUrl: './login.component.html',styleUrls: ['./login.component.css']
})
export class LoginFormComponent {info:FormGroup;constructor(private fb:FormBuilder){this.createForm();}createForm() {this.info = this.fb.group({name: ['jack', Validators.required, checkNameValidator()],password: ['', [Validators.required, PasswordValidator()]]});}onSubmit() {console.log(this.info.value);}
}
  • 我们需要先在构造函数中注入FormBuilder,最好新建一个方法来初始化表单,这里我们在createForm方法中初始化表单。
  • 借助FormBuilder我们可以通过参数来构建表单组,参数的结构与使用new基本一致,就不需要重复的写new FormGroup(…)、new FormControl(…)了。

Angular表单中的FormControl、FormGroup、FormBuilder、FormArray相关推荐

  1. Angular中响应式表单 FormBuilder、FormControl 、FormGroup、FormArray、setControl、setValue用法总结

    以我的项目作为示例,总结一下Angular响应式表单的应用和常用的方法: 1.创建表单 form.ts代码 import { Component, OnInit } from "@angul ...

  2. angular 表单

    angular 表单 一.angular表单简介 Angular 提供了两种不同的方法来通过表单处理用户输入:响应式表单和模板驱动表单. 两者都从视图中捕获用户输入事件.验证用户输入.创建表单模型.修 ...

  3. angular4更改表单中显示的值_Angular 4 动态表单教程 Reactive Forms教程

    动态表单(React Forms)是一种动态构建表单的技术,用于解决有时候手动编写和维护表单所需工作量和时间会过大的问题.特别是在需要编写大量表单时.表单都很相似,而且随着业务和监管需求的迅速变化,表 ...

  4. angular表单验证 1

    表单验证 通常,我们都需要对用户的表单输入做验证,以保证数据的整体质量. Angular也有两种验证表单的形式: 使用属性验证,用于模板驱动表单: 使用验证器函数进行验证,用于响应式表单. 验证器(V ...

  5. Angular 表单验证

    模板驱动验证 使用模板驱动验证需要依赖于原生的HTML表单验证器 Angular 会用指令来匹配具有验证功能的这些属性. 原生的HTMl验证器主要分两种 通过语义类型来进行定义 通过验证相关的属性来进 ...

  6. Angular 表单验证类库 ngx-validator 1.0 正式发布

    背景介绍 之前写了一篇 <如何优雅的使用 Angular 表单验证>,结尾处介绍了统一验证反馈的类库 ngx-validator ,由于这段时间一直在新模块做微前端以及相关业务组件库,工具 ...

  7. 如何优雅的使用 Angular 表单验证

    随便说说,这一节可以跳过 去年参加 ngChine 2018 杭州开发者大会的时候记得有人问我: Worktile 是什么时候开始使用 Angular 的,我说是今年(2018年) 3 月份开始在新模 ...

  8. 一个解决表单中的文字和文本区域(textarea)上对齐的方法

    一个解决表单中的文字和文本区域(textarea)上对齐的方法 参考文章: (1)一个解决表单中的文字和文本区域(textarea)上对齐的方法 (2)https://www.cnblogs.com/ ...

  9. 在HTML文件的表单中添加{%csrf_token%}便可以解决问题

    在HTML文件的表单中添加{%csrf_token%}便可以解决问题 参考文章: (1)在HTML文件的表单中添加{%csrf_token%}便可以解决问题 (2)https://www.cnblog ...

最新文章

  1. 在SQL Server中保存和输出任意类型的文件
  2. 基于asp.net2.0中membership系统角色、用户、资源的权限设计
  3. RMSE、MAE等误差指标整理
  4. django批量form表单处理
  5. boost::hana::detail::fast_and用法的测试程序
  6. android hook 实例,代码实例分析android中inline hook
  7. 只开窗不镀锡_推拉窗和平开窗哪个好?
  8. SLAM GMapping(5)运动模型
  9. 使用 CSS 接收用户的点击事情并对相关节点进行操作
  10. 【讨论】对技术的掌握到底应该又多深?
  11. 从零开始学习Sencha Touch MVC应用之十四
  12. c语言中 x20是什么意思,转义字符的问题,\ x00- \ x20是什么意思
  13. lise什么意思中文翻译_list中文是什么意思?
  14. EntityFramework安装失败
  15. 去除word转pdf时的图片黑边
  16. java 线程与线程池详解
  17. 房产|1月全国70城房价出炉!疫情放开后你关心的城市房价有何变化
  18. C语言-输入一个整数把每位数字转换为英文
  19. remosaic插值算法_手机镜头像素:硬件直出和插值有啥区别?
  20. 【FPGA基础篇】底层结构组成

热门文章

  1. StringBuilder清空方式
  2. 火爆网络的游戏解说,开创LOL“幽默化”的新时代
  3. 物理DG删除归档测试
  4. 重温清除浮动方法,逐句解释clearfix的意义
  5. 浅谈ffmpeg对ps文件格式的转换
  6. 用easyx画超级好看的动态图
  7. 普耐尔momo7w安装Linux,momo7w安装单系统安卓或双系统安卓+windows教程第七次修订版.doc...
  8. Android向SD卡写入文件
  9. 内网横向移动——SNMP信息收集
  10. SPI Bit-banging方法的实现