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