【问题标题】: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。

【问题讨论】:

    标签: html angular forms components


    【解决方案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】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 2017-09-17
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多