Angular:在 NgForm 的自定义输入组件中调用 markAsDirty()
Posted
技术标签:
【中文标题】Angular:在 NgForm 的自定义输入组件中调用 markAsDirty()【英文标题】:Angular: Call markAsDirty() in Custom Input Component from NgForm 【发布时间】:2017-09-24 05:07:58 【问题描述】:我实现了一个自定义组件,它是 NgModel 输入的包装器。我将它们与 ControlValueAccessor 连接起来。它运行良好,我可以轻松地从我的父组件访问值。
但是,如果我尝试调用 markAsDirty(),所触摸的标志只会在我的组件上发生变化,它对我在组件内的输入没有影响。我举个例子:
// Parent Component
onSubmit(form: NgForm)
this.form.controls.registerEmail.markAsDirty();
// Thats how the component looks like in my form:
<form #form="ngForm" (ngSubmit)="onSubmit(form)" [ngClass]="'has-error': !form.valid">
<form-text label="E-Mail" name="registerEmail" email required placeholder="" [(ngModel)]="eMail"></form-text>
</form>
// Result
<form-text label="E-Mail" name="registerEmail" class="ng-untouched ng-invalid ng-dirty">
<label for="form-text-2">E-Mail</label>
<input class="input-control invalid ng-untouched ng-pristine ng-invalid" type="text" id="form-text-2">
</form-text>
您可以看到表单文本具有“ng-dirty”类,内部的输入保持原始状态。
为了实现我的自定义组件,我使用了您在网络上找到的许多说明之一。这是我用过的:angular2 custom form control with validation json input
我想在按下提交按钮时将每个输入字段标记为脏。因为我的验证出现了,所以当你模糊输入时。
我发现我的组件从 ControlValueAccessor 继承存在问题。我的组件和我的 NgForm 之间的唯一联系是通过它的 NgModel。 NgForm 可以将我的组件用作 FormControl,因为它有自己的 NgModel。在事件中,可以在两个方向上传递值。但是使用 markAsDirty() 或 markAsTouched() 之类的方法是不可能的。在组件内部没有问题。但是我的 NgForm 无法真正访问组件。仅适用于 NgModel。
有什么方法可以实现吗?我认为这并不难弄清楚,但我为此苦苦挣扎了很长时间。我目前唯一的解决方案是使用 jQuery 遍历每个输入以触发焦点。必须有一个更清洁的解决方案。
谢谢
【问题讨论】:
我也有同样的问题。有关于这个问题的消息吗? 如果不起作用,请将formControl
添加为输入组件的输入并调用方法。 <form-text [control]="form.controls.eMail">
。我们遇到了类似的问题,这是最实用的方法,因为子输入组件除了输入之外,不知道其父组件的任何内容。
@mchl18 你能解释一下或提供一个示例代码吗?这个问题快把我逼疯了
【参考方案1】:
您可以在实现ControlValueAccessor
的组件中传递表单的dirty
属性作为输入,然后使用ReactiveFormsModule
和FormControl
更新您的内部输入的状态。
保存表单的组件:
<form #myForm="ngForm" (submit)="onSubmit($event)">
<my-input name="my-input" [(ngModel)]="myInput" [formDirty]="myForm.dirty"></my-input>
<button type="submit">Submit</button>
</form>
然后在实现ControlValueAccessor
的组件中:
ngOnChanges( formDirty : SimpleChanges)
if (formDirty.currentValue)
this.inputCtrl.markAsDirty();
else
this.inputCtrl.markAsPristine();
Here you can find the relevant snippet.
【讨论】:
谢谢大佬,终于轻松了。我使用 [formSubmitted]="myForm.submitted" 在表单提交后显示错误消息。【参考方案2】:当您希望控件状态设置为已触摸时,您需要从组件内部调用 onTouched() (this._onTouchedCallback)。 this._onChangeCallback 也一样
例如通过将 (ngModelChange)="onTouched(value)" 添加到 my-custom-input 中的输入标签
复制自: https://github.com/angular/angular/issues/10151
【讨论】:
【参考方案3】:问题是当脏状态改变时没有简单的方法来获得任何通知。见https://github.com/angular/angular/issues/10887。
辅助指令:
@Directive(
selector: 'my-input'
)
export class MagickDirective implements DoCheck
constructor(private control:NgModel)
ngDoCheck(): void
//you can do whatever you want
if(this.control.dirty)
(this.control.valueAccessor as MyInputComponent).setDirty(true);
【讨论】:
以上是关于Angular:在 NgForm 的自定义输入组件中调用 markAsDirty()的主要内容,如果未能解决你的问题,请参考以下文章
自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证
我可以在 Angular 4 的同一个组件中使用两个 ngForm 吗?