我有一个大型的反应形式,它具有条件验证,基于从应该触发验证的多选输入所做的选择 . 我注意到,当选择或取消选择某个项目时,整个表单被标记为无效(使用ng-invalid类),但内部子输入在它们应该有效时表示无效,反之亦然UNTIL你要么关注输入或者如果您只是在页面上的任意位置单击选择 .
https://stackblitz.com/edit/angular-6mbw5r
Repro步骤:
-
打开开发工具并注意整个标记在加载时设置为ng-invalid . 应该无效的唯一字段是DEA表单字段 .
-
从服务水平多重选择中删除受控物质 . 请注意,表单从
class="ng-untouched ng-pristine ng-invalid"
到class="ng-untouched ng-invalid ng-dirty"
UNTIL单击ng-select
(或任何其他字段)组件 . 然后它转到class="ng-dirty ng-touched ng-valid"
. -
注意必要字段如何根据表单的当前状态进行更改或不更改,直到发生其他一些操作(如更改焦点) .
备用Repro步骤:
- 加载页面并选中Veteranarian复选框 . 这应该会触发状态许可证无效,但直到您点击其他位置才会触发 .
我有OnPush变化检测,并确保在任何地方我做任何条件变化,我 markForCheck()
. 我还将整个表单组更新策略设置为 'change'
,根据我的理解,应该在表单字段更改值后立即触发验证 .
我已经阅读了很多关于如何正确地使用角度(https://www.dev6.com/Angular2-Conditional-Validation-with-Reactive-Forms,https://dzone.com/articles/how-to-do-conditional-validation-on-valuechanges-m)中的反应形式进行条件形式验证的文章 .
我还以为我已经弄明白了这两个问题:https://github.com/angular/angular/issues/13200 https://github.com/angular/angular/issues/14542(stackblitz链接中的第161行),但这也没有帮助 .
它似乎与点击事件后发生的变化检测有关(我理解在事件,异步事件等过程中发生检测)或 valueChanges
订阅不能在兄弟组件之间准确更新,直到焦点发生变化 . 我推测 updateValueAndValidity()
会触发变化检测,但它似乎没有 .
任何帮助都会很棒!
1 回答
我已经分解了您的示例代码并进行了一些更改以解决问题,现在它可以正常工作,根据您的需要 . 如果您浏览stackblitz link并单击'Veterinarian'复选框,则需要State字段 . 一旦取消,则不需要State字段 .
我使用“@ rxweb / reactive-form-validators”进行条件验证 .
我做了哪些更改,请参阅以下步骤:
2.在StateLicense属性中,您将分配FormControl对象 . 我删除了FormControl对象并以其他方式分配值和验证器 . 我还为条件验证添加了'RxwebValidators.required',因为角度验证器不提供条件验证 . 请参阅以下代码(第125至127行):
4.删除了changeDetection:ChangeDetectionStrategy.OnPush .
总的来说,我可以说,这可以通过rxweb required conditional validator来实现 .
如果您有任何疑问,请告诉我 .