0

我已经实现了一个带有自定义验证的自定义表单控件,但是一旦提交父表单,我就无法将控件标记为无效我希望当用户按下提交时,控件会失效.. 到目前为止,只有在触摸它时它才会失效.. 在我的 onDoCheck 中,我设法读取了 form.isSubmitted 属性,但我注意到该控件仍被标记为“有效”

即使我构建逻辑并在我的 onDoChek 中将其强制为无效.. 这样在提交时的父组件中我无法检查控件的有效性,因为我会在 onSubmit 回调之后设置它.. 我在这里缺少什么?

我能想到的丑陋修复是添加

this.form.get('test').updateValueAndValidity();
this.form.get('test').markAsTouched(); 

在 onSubmit 回调上,但不这样做不应该开箱即用吗?

这里是stackblitz: https ://stackblitz.com/edit/angular-k5un7v?file=src%2Fapp%2Fcustom-input%2Fcustom-input.component.ts

任何帮助是极大的赞赏

4

4 回答 4

0

对于那些感兴趣的人,我找到了一个更好的解决方案,我不需要弄乱父组件中的表单

https://stackblitz.com/edit/angular-7gmzya?file=src%2Fapp%2Fcustom-input%2Fcustom-input.component.ts

基本上我所要做的就是

 ngAfterViewInit() {
    //console.log("IS REQUIRED? ", this.required)
    if (this.required && this.ngControl && this.ngControl.control) {
      this.ngControl.control.setValidators(this.validate);
      //UPDATING VALIDITY:
      setTimeout(()=> {
       this.ngControl.control.updateValueAndValidity();
      }
      );
    }
  }

在 ngDoCheck 中:

this.errorState = this.ngControl.invalid && (this.ngControl.touched);

就是现在:

this.errorState = this.ngControl.invalid && (this.ngControl.touched || this.form.submitted);

这样组件的行为就像一个标准的角度形式控件,但我认为它并不完美,因为我不得不求助于 setTimeout,所以如果你们有一个更优雅的解决方案,我将把它留作未解决..

于 2020-12-04T10:35:55.030 回答
0

在提交并检查markAllAsTouched()表单上的验证运行之前。

于 2020-12-03T17:34:03.490 回答
0

我认为您的问题在验证中。

当我评论循环部分时,请参见下图。

我不确定您的验证的业务要求是什么。但只需确保该部分首先返回正确的值。

在此处输入图像描述

于 2020-12-04T03:46:18.837 回答
0

即使我的解决方案也不完美,我建议您在providers组件中添加 NG_VALIDATORS。

目前,您的表单是valid应用程序启动的时间,它不应该。实际上,如果我运行您的示例,则以下属性是错误的true

Custom input valid: {{form.get('test').valid}} 
Form valid: {{form.valid}}

providers当我在您的自定义 CVA 组件中添加 NG_VALIDATORS 时,这些属性将变为false,因为它们应该:

{
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true
},

只需添加这些行,您的表单和自定义字段现在在应用程序启动时无效,因为您已经validate()在组件中添加了一个方法。

无论如何,由于 Material 组件的行为,mat-error 仍然没有显示错误。来自文档:

mat-error:错误最初是隐藏的,并且在用户与元素交互或提交父表单后将显示在无效的表单字段上。来源:https ://material.angular.io/components/form-field/overview

我不知道您是否可以轻松更改此行为,但现在您可以创建自己的样式并且表单应该可以正常工作。或者,正如其他人告诉你的那样,在提交后将它们标记为已触摸。

我希望这个建议可以帮助您找到解决问题的另一种方法。

这里是我的 StackBlitz: https ://stackblitz.com/edit/angular-vgyug5?file=src%2Fapp%2Fapp.component.html

于 2020-12-05T03:49:25.413 回答