模板驱动表单中的表单验证问题

Posted

技术标签:

【中文标题】模板驱动表单中的表单验证问题【英文标题】:Problem with form validation in template driven form 【发布时间】:2019-04-16 12:03:09 【问题描述】:

我正在使用 Angular 6 开发一个 Web 应用程序。我想创建一些受 html 输入组件启发的自定义组件。例如:

CustomComponent.ts(打字稿)

  @Component(
    selector: 'custom-component',
    templateUrl: './custom-component.html',
    providers: [
       
         provide: NG_VALUE_ACCESSOR,
         multi: true,
         useExisting: forwardRef(() => InputTextComponent)
       
    ]
    )
    export class CustomComponent 

      @Input() name: string;
      @Input() isRequired: boolean;
    

CustomComponent.html(模板)

<input type="text"
   [attr.name]="name"
   [required] = "isRequired"
/>

我有这个问题。假设我们在这个模板中使用我的组件:

<form #myForm="ngForm" ngNativeValidate>
  <custom-component
  name="myName"
  [isRequired] = true
  ngModel
  ></custom-component>
<button type="submit" (click)="method()">Click</button>

required 属性在&lt;input type="text/&gt;&lt;custom-component&gt; 的包装组件)中正确初始化。问题是这样的(这是一个 Angular 问题!):在这个使用代码中:

  method() 
    console.log(this.myForm.valid);
  

对象myForm.valid(其中myForm 与上一个模板中的#myForm 相关联)始终返回true 值,即使在文本字段中没有输入任何内容。这种行为是错误的:如果我不在必填字段中插入任​​何内容,我希望此值为 false。

【问题讨论】:

【参考方案1】:

要将验证添加到您的自定义输入组件,您应该将以下内容添加到您的提供程序:


  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => InputTextComponent),
  multi: true

您必须在 InputTextComponent 中实现默认方法:

validate(control: AbstractControl): ValidationErrors | null 
    return null;

如果您使用您通过 NG_VALUE_ACCESSOR 实现的 writeValue() 方法正确更新了组件中名为 value 的属性,然后确保调用(您可以通过在默认输入上实现更改事件):

this.propagateChange(this.value);

最后将您的 isRequired 输入更改为默认的 required 属性。

 @Input() required: boolean;

您的 NgModel 现在应该可以正确更新了。

编辑: 避免使用 required (但这是正确的方法)。在验证方法中放置以下代码:

validate(control: AbstractControl): ValidationErrors | null 
    return this.isRequired && this.value.length === 0 :  required: true  : null;

当 Angular 运行它自己的验证时,它会调用这个方法。当此方法返回除 null 以外的任何内容时,该对象将添加到 FormControl 和 NgModel 中的 errors 属性中。

这是一个巨大的话题,有一些很棒的文章正确地解释了这一切。但是,正如所问的,这应该可以解决它。

【讨论】:

谢谢,除了最后一步,我什么都做了。为什么我需要编辑输入名称(@Input() required: boolean;)以及这如何反映在我的自定义组件的模板中? 好的,它工作。但是如果我想保留 isRequired 属性怎么办? 我想避免使用调用者的“必需”属性...我更喜欢使用调用者的自定义属性“isRequired” 当使用 NgModel 和 ControlValueAccessor 时,你通知 Angular 你将把这个组件当作默认的 HTML 输入。您可以使用 isRequired,但是,您的输入元素不是组件内的输入,而是您的 InputTextComponent 本身。我将更新我的答案以包含解决方法,但是,我建议不要这样做。这就是为什么建议像使用实际输入一样使用 require。【参考方案2】:

您应该检查表单是否脏并且是否有效。所以两者都必须是真的。否则显示它没有被改变。

【讨论】:

以上是关于模板驱动表单中的表单验证问题的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 模板驱动的表单 - 控制器中的自定义验证器功能

angular2模板驱动的表单验证问题

如何在模板驱动的表单中为 ngModelGroup 添加自定义验证

模板驱动表单(实验部分)

Angular 2.0 中的模型驱动表单验证问题

Django:模板中的 Crispy 表单验证错误