响应式表单为@angular/form包提供的ReactiveFormsModule,核心思想是围绕流observable,对表单进行数据设置、获取、校验等
Angular/common包里的表单
表单项有层级结构,表单项基础构造类为FormControl,当页面片段需要使用多字段聚合的表单,需要用到FormGroup或FormArray,注意FormArray不能独立使用,需要集成在FormGroup里,FormArray一般用于不确定多少表单项数组的场景,代码例子如下
FormControl校验状态包括 VALID、 INVALID、 PENDING(校验中) 、DISABLED,还有两个标志位表明表单项有没有UI操作过,pristine、touched
FormControl FormGroup FormArray都继承自 AbstractControl ,所以他们都拥有共同的属性和方法,比如上面的状态、以及validator,FormGroup FormArray也可以有自己的校验器,只不过我们很少用
校验最核心的方法
此方法只针对enable的表单项完成校验状态的更新(保存到control.status属性,并更新errors对象),并且根据emitEvent配置项决定是否emit valueChanges和statusChanges,根据onlySelf配置项决定是否对父级表单项进行校验;
界面上的校验提示是根据校验状态errors对象来显示的
父级表单可能是FormGroup或FormArray,根据代码可以看出如何判断表单状态,判断优先级从高到低
1、所有子项都为disable,那么此表单为DISABLED
2、errors存在,为INVALID
3、任一项为校验中,此表单为PENDING
4、任一项为INVALID,此表单为INVALID
表单项的方法:初始构造、addControl、setValue、patchValue,enable,disable,reset内部都会调用updateValueAndValidity;唯一的特例的setValidators方法,所以一般推荐修改校验器后,需要updateValueAndValidity将表单项的状态更新
表单多层级结构下状态的联动
各表单在执行自身状态校验时,需要保证表单的子项的状态都是最新,否则自身的状态校验就有问题。上面的源码也说明这一点,子control的校验先行,然后再执行本身的校验;
其次,patchValue时默认onlyself:false,会在执行完自身校验后,再向上对父级进行状态更新
例子:
表单层级结构如下
每个层级的表单项都有自己的validator,如果我们对B1执行patchValue时,设置了onlyself:true,那么在执行完B1.patchvalue后,A B的状态不会更新,若业务中需要使用到A B的状态,那么会有问题
zorro包里的表单
状态在上面的基础上封装了一层,success warning error validating,
界面展示校验信息对应
设置zorro表单状态的前提是收到statusChanges流推送,意味着若patchValue时设置emitEvent:false,则zorro表单状态不会有任何更新,但注意formControl的校验状态仍然会更新
zorro表单在获取状态时,会根据dirty touched标志位做判断,若表单为未操作过的状态,则不设置表单状态,这也是为什么在zorro表单提交时,会要求下面这样写的原因,这样才能让zorro每个表单项都更新到最新状态
最佳实践优化:
1、注明是zorro下的表单
2、在addControl、setValue、patchValue,enable,disable,reset方法内部都会调用updateValueAndValidity,由于updateValueAndValidity会默认往上找所有父表单项;当确认业务层面不使用父级表单状态,那么可以加上onlySelf:true,避免不必要的性能损耗
3、响应式表单不推荐和ngModel ngModelChange一块使用,响应式的核心思想在于围绕observable的使用,充分利用好valueChanges以及statusChanges
标签:状态,单项,zorro,FormArray,校验,表单,响应,angular From: https://www.cnblogs.com/querybest/p/18512508