angular material 带有自定义验证的自定义表单控件组件不会在表单提交时触发

angular material custom form control component with custom validation doesn't trigger on form submit

我已经实现了带有自定义验证的自定义表单控件,但是在提交父表单后我无法将控件标记为无效 我希望当用户按下提交时控件失效..到目前为止它只有在触摸它时才会失效..在我的 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

非常感谢任何帮助

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

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

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

我不确定您的验证有哪些业务要求。但只要确保该部分首先返回正确的值即可。

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

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();
      }
      );
    }
  }

在 ngDo 中检查这个:

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

现在是:

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

这样组件的行为就像一个标准的 angular 表单控件,但我认为它的解决方案并不完美,因为我不得不求助于 setTimeout,所以我将此作为未解决的,如果你们得到了一个更优雅的解决方案..

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

目前您的表单在应用程序启动时是 valid,它不应该。 事实上,如果我 运行 你的例子下面的属性是错误的 true :

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

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

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

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

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

mat-error: Errors are hidden initially and will be displayed on invalid form fields after the user has interacted with the element or the parent form has been submitted. Source: https://material.angular.io/components/form-field/overview

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

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

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