模板驱动表单中的表单验证问题
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
属性在<input type="text/>
(<custom-component>
的包装组件)中正确初始化。问题是这样的(这是一个 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 - 模板驱动的表单 - 控制器中的自定义验证器功能