1

Angular的ReactiveForms的使用教程请参考
Angular 4.x Reactive Forms

前言

Angular官网有关ReactiveForms相关api走读,做下笔记。

FormControl、FormGroup、FormArray。

使用Angular的ReactiveForms时,我们需要先了解其三大构件
FormControl、FormGroup、FormArray。

AbstractControl

这是FormControl,FormGroup和FormArray的基类。
它提供了所有控件和group控件的一些共同行为,例如运行验证器,计算状态和重置状态。 它还定义了所有子类之间共同的属性,如值,有效和脏。 不应该直接实例化。

class AbstractControl {
    constructor(validator: ValidatorFn, asyncValidator: AsyncValidatorFn)
    validator : ValidatorFn
    asyncValidator : AsyncValidatorFn
    value : any
    parent : FormGroup|FormArray 
    status : string
    valid : boolean
    invalid : boolean
    pending : boolean
    disabled : boolean
    enabled : boolean
    errors : ValidationErrors|
}

常用属性

  • value: 控件的值

  • parent: 可用来获取父控件

  • valid: 控件值有效

  • invalid: 控件值无效

  • errors: 错误对象,一般可用来存放错误信息

FormControl和FormControlName

  • FormControl用来跟踪单个表单控件的值和验证状态。

  • FormControlName将现有FormGroup中的FormControl与表单控件元素同步。

//name 是FormGroup中的control属性名
<input type="text" formControlName="name">
class FormControl extends AbstractControl {
    constructor(formState?: any, validator?: ValidatorFn|ValidatorFn[], asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[])
    setValue(value: any, {onlySelf, emitEvent, emitModelToViewChange, emitViewToModelChange}?: {?: boolean,?: boolean,?: boolean,?: boolean}) : void
    patchValue(value: any, options?: {?: boolean,?: boolean,?: boolean,?: boolean}) : void
    reset(formState?: any, {onlySelf, emitEvent}?: {onlySelf?: boolean,?: boolean}) : void
    registerOnChange(fn: Function) : void
    registerOnDisabledChange(fn: (isDisabled: boolean) => void) : void
}
创建FormControl

直接设置控件值

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

您还可以在实例化时使用表单状态对象初始化控件,其中包括值和控件是否禁用。

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

传入控件值和验证器
要将同步验证器(或同步验证器数组)与控件一起包含,请将其作为第二个参数传递。 异步验证器也受支持,但必须分别作为第三个参数传递。

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

FormGroup和FormGroupName

  • FormGroup:跟踪一组FormControl实例的值和有效性状态。如果组中的一个控件无效,则整个组将变为无效。

  • FormGroupName:将嵌套FormGroup同步到DOM元素。

嵌套formgroup里的formgroup的绑定

<fieldset formGroupName="address">
class FormGroup extends AbstractControl {
    constructor(controls: {[key: string]: AbstractControl}, validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn)
    controls : {[key: string]: AbstractControl}
    registerControl(name: string, control: AbstractControl) : AbstractControl
    addControl(name: string, control: AbstractControl) : void
    removeControl(name: string) : void
    setControl(name: string, control: AbstractControl) : void
    contains(controlName: string) : boolean
    setValue(value: {[key: string]: any}, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    patchValue(value: {[key: string]: any}, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    reset(value?: any, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    getRawValue() : any
}
创建FormGroup
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'

您还可以将组级验证器作为第二个参数或组级异步验证器作为第三个参数。 当您要执行考虑多个子控件的值的验证时,这些将派上用场。

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};
}

FormArray和FormArrayName

  • FormArray:跟踪FormControl,FormGroup或FormArray实例数组的值和有效性状态。

  • FormArrayName:将嵌套的FormArray同步到DOM元素。
    嵌套formgroup里的formgroup的绑定

<div formArrayName="formarray">
class FormArray extends AbstractControl {
    constructor(controls: AbstractControl[], validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn)
    controls : AbstractControl[]
    at(index: number) : AbstractControl
    push(control: AbstractControl) : void
    insert(index: number, control: AbstractControl) : void
    removeAt(index: number) : void
    setControl(index: number, control: AbstractControl) : void
    length : number
    setValue(value: any[], {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    patchValue(value: any[], {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    reset(value?: any, {onlySelf, emitEvent}?: {onlySelf?: boolean, emitEvent?: boolean}) : void
    getRawValue() : any[]
}
创建FormArray
const arr = new FormArray([
  new FormControl('Nancy', Validators.minLength(2)),
  new FormControl('Drew'),
]);
console.log(arr.value);   // ['Nancy', 'Drew']
console.log(arr.status);  // 'VALID'

您还可以将第二个arg或数组级异步验证器作为第三个参数包含数组级验证器。 当您要执行考虑多个子控件的值的验证时,这些将派上用场。

FormGroup和FormArray区别

FormArray是FormGroup的一个变体。 关键的区别在于它的数据被序列化为一个数组(而不是在FormGroup的情况下被序列化为一个对象)。 当您不知道组内将出现多少控件(如动态表单)时,这可能会特别有用。要更改数组中的控件,请在FormArray本身中使用push,insert或removeAt方法。 这些方法确保控件在窗体的层次结构中正确跟踪。

FormBuilder简化编写

它基本上是语法糖,缩短了新的FormGroup(),新的FormControl()和新的FormArray()样板,可以建立更大的形式。

class FormBuilder {
  
  // 基于controlsConfig、extra信息(添加验证器),创建FormGroup对象
  group(controlsConfig: {[key: string]: any}, extra: 
      {[key: string]: any} = null): FormGroup {}
  
  // 基于formState、validator、asyncValidator创建FormControl对象
  control(
      formState: Object, validator: ValidatorFn|ValidatorFn[] = null,
      asyncValidator: AsyncValidatorFn|AsyncValidatorFn[] = null): FormControl {}
  
  //基于controlsConfig、validator、asyncValidator创建FormArray对象
  array(
      controlsConfig: any[], validator: ValidatorFn = null,
      asyncValidator: AsyncValidatorFn = null): FormArray {}
}
this.user = this.fb.group({
    name: ['', [Validators.required, Validators.minLength(2)]],
    account: this.fb.group({
      email: ['', Validators.required],
      confirm: ['', Validators.required]
    })
  });

Reactive Forms使用总结

以上介绍FormControl、FormGroup、FormArray的API也仅仅只是介绍其构造方法。使用Reactive Forms,无非最主要的是

  • 构建form对象及其绑定到DOM表单元素

  • 添加验证器

  • 显示错误

  • 获取某个控件及其值

  • 监听数据和状态变化

构建form对象及其绑定到DOM表单元素、添加验证器

上述已讲

显示错误

表单控件有一些状态类型属性,如pristine, dirty, valid,invalid,touched,untouched表示某一种状态是否为真。验证的错误信息结果,会放在name.errors里。

<div [hidden]="userForm.controls.name.valid||userForm.controls.name.pristine">
    <p *ngIf="userForm.controls.name.errors?.minlength">姓名最小长度为3</p>
    <p *ngIf="userForm.controls.name.errors?.required">必须输入姓名</p>
</div>

获取control

formgroup.get('first');  
formgroup.get('name.first')  
this.form.get(['person', 'name']);
formgroup.controls.key

获取控件值

control.value

设置控件值

AbstractControl.setValue or AbstractControl.patchValue

formgroup.setValue({...}) //设置整体  
formgroup.patchValue({xxx:xxx}) //设置单个control值
const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.value);   // [null, null]
arr.patchValue(['Nancy']);
console.log(arr.value);   // ['Nancy', null]

监听值和状态

AbstractControl.valueChanges  
AbstractControl.statusChanges

其他

FormGroupDirective

将现有的FormGroup绑定到DOM元素。那他和FormGroupName有什么区别?
此伪指令接受顶级FormGroup实例。 然后,它将使用此FormGroup实例将任何子FormControl,FormGroup和FormArray实例与子FormControlName,FormGroupName和FormArrayName指令进行匹配。

<form [formGroup]="form" (ngSubmit)="onSubmit()">

FormControlDirective

将独立的FormControl实例同步到表单控件元素。

import {Component} from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
@Component({
  selector: 'example-app',
  template: `
     <input [formControl]="control">
     <p>Value: {{ control.value }}</p>
     <p>Validation status: {{ control.status }}</p>
     <button (click)="setValue()">Set value</button>
  `,
})
export class SimpleFormControl {
  control: FormControl = new FormControl('value', Validators.minLength(2));
  setValue() { this.control.setValue('new value'); }
}

laoergege
60 声望3 粉丝

引用和评论

0 条评论