Angular[2-6] 中FormsModule与ReactiveFormsModule的用途同时一次性说清楚其相关的一些概念

在新版本的 Angular 中并没双向绑定的功能,而在表单中所谓的双向绑定则是通过属性绑定和事件绑定来完成的。

目前来说,表单的操作的两种形式:FormsModuleReactiveFormsModule。这两种形式分别作用于:模板式表单和动态构建式的表单。

FormsModuleReactiveFormsModule分别提供了一系列不同的指令集合。

使用表单操作时,必须引入以上的模板,否则会直接报错。

FormControl

FormControl 是 Form 表单中的一部分且不可见,通常用在一些比较简单的元素上,如文本框。

    const c = new FormControl(value,Validators)
    第一个参数表示表单的初始值,第二个参数表示表单的验证器,如:Validators.required

FormControl 在开发中常用到的属性有:value, status, errors

  • value: 表单当前值
  • status: 表单当前状态,无效还是有效
  • errors:表单当前错误集合(表单的验证器可以设置多个)

FormGroup

FormGroup 是一个固定FormControl表单元素的集合

    const c = new FormGroup({
        name:new FormControl('lisi',Validators.required),
        addr:new FormControl('shenzhen',[Validators.required,...])
    })
    
    const c = new FormControl({
        name:new FormControl('lishi'),
        contract:new FormGroup({
            mobile:new FormControl('10086'),
            wechat:new FormGroup('wechat')
        }),
        langular:new FormArray([
            new FormControl('Javascript'),
            new FormControl('Angular'),
            new FormControl('Vue')
        ]),
        remark:new FormControl('--')
    })
    ...

FormGroup 用于管理一级不同控件类型的集合,可用于构建ReactiveFormsModule的表单时动态创建表单对象,与FormControl一样有着同样的验证功能。

FormGroup下的任意一个FormControl的数据发生的变化,FormGroup的数据也会同时发生变化。但FormGroup的状态和errors有点不一样,FormGroup下所有FormControl的errors都是独立的,且每个FormControl都有自己的errors 集合。

FormGroup状态的验证规则,如下:

  • 任一FormControl 的状态是无效的,则认定FormGroup的状态验证是无效的
  • 若所有的FormControl的状态被验证是有效的,但 FormGroup有错误发生则也认定为FormGroup状态为无效的
  • 若所有的FormControl的状态被验证是有效的,且 FormGroup没有错误提示则认定FormGroup的表单状态有效

通过以上这几条规则可以看出,FormGroup 很适合用在动态创建表单的场景(动态添加输入框,动态添加按钮...)

FormArray

FormArray 用于管理一组具有相同控件类型的集合

    const c = new FormArray([
        new FormControl('name',Validators.required),
        new FormControl('addr',Validators.required),
        ...
    ])

与FormControl、FormGroup一样,FormArray同样具有 value、status、errors 。

更新 Form Model

更新 Form Model 的方式:setValuepatchValue

  • setValue 更新所有数据,使用strict模式同时要求value完全匹配Form的结构才会更新数据不然会报错
  • patchValue 更新当前控件数据,使用标准模式,不要求value完全匹配Form结构也会更新数据且不报错

从上面这两条规则可以知道:

setValue 用于更新一组值
patchValue 用于更新某个值

验证器(Validators)

Form表单中所谓的验证器其实就是一组普通函数操作的集合

    class Validators {
        static required(control):{[key:string]:any}{
            return isEmptyValue(control.value) ? {'required':true} : null;
        }
        
        static minLen(min:number):ValidatorFn {
            return (control):{[key:string]:any} => {
                const len:number = control.value ? control.value.length : 0;
                return len < min ? {'requireLen':min,'actualLength':len} : null;
            }
        }
    }

组件验证器Validators(合并多个为一个):

    const ValidatorFn = Validators.compose([
        Validators.minLen(10),
        Validators.required,
        Validators.maxLen(20)
    ])
    
    const email = new FormControl('demo@qq.com',ValidatorFn);

监听数据变化

时时响应控件数据的变化:

    const c = new FormControl({
        name:new FormControl('lishi'),
        contract:new FormGroup({
            mobile:new FormControl('10086'),
            wechat:new FormGroup('wechat')
        }),
        langular:new FormArray([
            new FormControl('Javascript'),
            new FormControl('Angular'),
            new FormControl('Vue')
        ]),
        remark:new FormControl('--')
    })
    
    c.valueChanges.subscribe(r=>console.log('changed',r))
    c.statusChanges.subscribe(r=>console.log('changed',r))
    

FormGroup 在模板中的使用

在Form表单中的使用

    <form [formGroup]="loginForm">
      <input type='text' formControlName='uname' />
      <input type='text' formControlName='upwd' />
      
      <p>{{loginForm.get('uname').value}}</p>
      <p>{{loginForm.get('upwd').value}}</p>
      <p>{{loginForm.value | json}}</p>
    </form>

ReactiveForms 表单使用的几个条件

ReactiveForms 的成功使用需要以下几个条件:

  • 必须实现FormGroup 和 formControlName 这两个指令,否则不好意思直接报错
  • 必须手动构建Form Model
  • 绑定Form Model 与对象的dom结构中,如formControlName,formGroup
  • formControlName的值必须与formGroup对应的key值对应

实现自定义控件

ControlValueAccessor 功能类似于一个连接到ngModel的适配器(adapter),常用于构建自定义的元素类型或Angular组件中,如:


@Component({
  selector: 'form-text',
  template: `
    <div >
        <label>{{label}}:</label>
        <input type="text"  [(ngModel)]="value"
        placeholder="{{placeholder}}" >
    </div>
  `,
  providers: [
    {
      provide:NG_VALUE_ACCESSOR,
      useExisting:forwardRef(()=>FormTextComponent),
      multi:true
    }
  ]
})
export class FormTextComponent implements ControlValueAccessor {

  @Output() onChange: EventEmitter<any> = new EventEmitter<any>();
  
  public label:string = '用户名';
  public placeholder='请输入用户名';
  public innerValue: any;
  public changeFn: Function = () => {};
  
  get value(): any {
    return this.innerValue;
  };

  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.changeFn(v);
    }
  }

  writeValue(value: any) {
    if (value !== this.innerValue) {
      this.innerValue = value;
    }
  }

  registerOnChange(fn: any) {
    this.changeFn = fn;
  }

  registerOnTouched(fn: any) {
    //
  }
}

2018.5.9 天之骄子 深圳

来源:https://segmentfault.com/a/1190000014801031?utm_source=index-hottest


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。