【问题标题】:Angular form initially invalid when containing a valid custom component包含有效自定义组件时,Angular 表单最初无效
【发布时间】:2020-04-30 11:05:16
【问题描述】:

我有一个简单的 Angular (v8.0) 组件,它只包含一个带有 required 属性集的输入。我有一个模板驱动的表单,其中包含该组件并将其绑定到初始值。当应用程序启动时,输入的状态是有效的,因为它绑定了一个初始值。但是表格错误地无效。在对输入值进行任何更改后,表单状态就正确了,并且从此保持正确。

我在validate 方法实现中返回输入的验证状态,这似乎是问题的根源。如果我返回一个我根据控件的当前值自己构造的对象,它会正常工作。但是我宁愿避免这种情况,因为我将来需要其他验证状态,我不想手动检查它们。

我尝试在代码的不同位置添加对updateValueAndValidity 的调用,但这没有效果。

如何让表单的初始验证状态考虑嵌套自定义组件的状态?

这是组件的代码:

import { AfterViewInit, Component, ViewChild } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, Validator, NgModel } from "@angular/forms";

@Component({
  selector: "my-input",
  template: '<input [(ngModel)]="value" required #model="ngModel" />',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: MyInputComponent,
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: MyInputComponent,
      multi: true
    }
  ]
})
export class MyInputComponent implements ControlValueAccessor, Validator {
  onChange: any = () => {};
  onTouch: any = () => {};

  @ViewChild("model", { static: true }) model: NgModel;

  private _value: string = "";

  set value(x: string) {
    if (this._value !== x) {
      this._value = x;
      this.onChange(x);
    }
  }
  get value() {
    return this._value;
  }

  writeValue(obj: any): void {
    this.value = obj;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouch = fn;
  }

  validate(c: FormControl) {
    return this.model.errors;
    //return this.value ? null : { required: true }; // this works!
  }
}

这是包含它的外部表单的代码:

import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <form #frm="ngForm">
      <my-input [(ngModel)]="myValue" name="myInput"></my-input>
    </form>
  `
})
export class AppComponent {
  myValue: string = "hello";
}

这是一个 StackBlitz:https://stackblitz.com/edit/angular-lp3xpa。在输入中添加或删除一个字符,表单状态变为有效。

【问题讨论】:

  • 我从您的 myInputComponent 组件中删除了验证功能,并在&lt;my-input [(ngModel)]="myValue" name="myInput" required&gt;&lt;/my-input&gt; 中添加了必需的属性,它按预期工作。您可以从外部控制您的验证。无需添加验证器
  • @Ashish 谢谢是的,但仅适用于表单状态。控件中的内部标签不再正确(请参阅here)。
  • 我已添加更改,请立即查看stackblitz.com/edit/angular-xmscak
  • @Ashish 是的,我明白你的意思。这可行,但这意味着myInputComponent 的每个实例都必须包含required 属性。我的初衷是将验证隐藏在myInputComponent 中而不包括属性,但仍然有气泡到表单。这可能吗?
  • 这绝不是一个好主意。当您创建共享组件时,您应该始终考虑所有这些事情。通过执行我建议您保留稍后更改逻辑的选项。您可以从材料组件或任何其他库中获取任何示例。

标签: angular typescript


【解决方案1】:

这听起来与this question 的问题相同,这表明使用setTimeoutwriteValue 手动触发另一个验证的解决方法。这似乎解决了问题。

MyInputComonent:

  writeValue(obj: any): void {
    this.value = obj;
    setTimeout(() => { this.onChange(this.value); }, 0);
  }

here

但这似乎是一个 hack。

【讨论】:

    猜你喜欢
    • 2020-10-22
    • 2014-05-17
    • 1970-01-01
    • 2021-03-15
    • 2018-09-03
    • 2018-06-16
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多