angular -响应式表单深入

响应式表单为@angular/form包提供的ReactiveFormsModule,核心思想是围绕流observable,对表单进行数据设置、获取、校验等

Angular/common包里的表单

表单项有层级结构,表单项基础构造类为FormControl,当页面片段需要使用多字段聚合的表单,需要用到FormGroupFormArray,注意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对象来显示的

 

父级表单可能是FormGroupFormArray,根据代码可以看出如何判断表单状态,判断优先级从高到低

1、所有子项都为disable,那么此表单为DISABLED

2、errors存在,为INVALID

3、任一项为校验中,此表单为PENDING

4、任一项为INVALID,此表单为INVALID

 

 

表单项的方法:初始构造、addControlsetValuepatchValueenabledisablereset内部都会调用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

 

 

 

posted @ 2024-10-29 11:04  天下无双之盛世奇观  阅读(55)  评论(0)    收藏  举报