我有一个名为ppo-currency-field
的自定义组件(Angular 6),带有以下模板:
<span class="display" tabindex="-1">{{formattedValue()}}</span>
<input #input class="input" type="number" [name]="name"
[tabindex]="tabindex" [readonly]="!!readonly || readonly===''"
[disabled]="!!disabled || disabled===''" [ngModel]="value"
(ngModelChange)="writeValue($event)" [ngModelOptions]="ngModelOptions">
我的组件代码包含以下行:
@Input() ngModelOptions: Object;
我将组件用于:
<ppo-currency-field [ngModel]="data.planningHours.rate"
(ngModelChange)="data.planningHours.rate = $event; recalc();"
[ngModelOptions]="{ updateOn: 'blur' }"
[disabled]="!data.containsPlanning ? '' : null"></ppo-currency-field>
如您所见,我正在尝试将ngModelOptions
从我的自定义组件传递到input
元素。但这是行不通的,因为未将update选项设置为“ blur”;实际上,似乎根本没有更新。
但是,当我直接在input
元素 上设置选项时,效果很好。
为什么我的传递功能不起作用,如何正确实施?
编辑:仅当我尝试使用ngModelOptions
作为属性名称时,才会出现此问题。如果我将其更改为例如options
,它可以工作。我猜这没关系,但是我试图使我的组件表现得尽可能多的本机输入字段。从直觉上讲,我不应该尝试重用Angular指令,但是在那种情况下,ControlValueAccessor
接口应该提供一个钩子来捕获这些选项,就像ngModel
/ {{1} }。
答案 0 :(得分:2)
自定义组件级别的ngModelOptions
属性适用于ControlValueAccessor,而不必将内部输入元素绑定到自定义@Input() ngModelOptions
属性,如您在this stackblitz中所见。
为了使自定义组件的ngModel
正确更新:
内部输入元素应随更改而更新(默认选项),以确保ControlValueAccessor也可以随更改而更新。
为使{updateOn: 'blur'}
选项起作用,当输入元素失去焦点时,应调用ControlValueAccessor的onTouched
事件回调:
<input ...
[ngModel]="value"
(ngModelChange)="writeValue($event)"
(blur)="onTouchedCallback()" />
在自定义组件中设置了onTouchedCallback
的地方:
registerOnTouched(fn: any): void {
this.onTouchedCallback = fn;
}
在Github上,kara中的issue 20384在注释中给出了需要调用onTouched
回调的说明:
顶层的
{updateOn: 'blur'}
功能取决于 实现下面的控制值访问器的registerOnTouched
正确地。看起来您的自定义组件保存了回调,但是 从来没有真正称呼它。由于未调用,因此值不会 正确更新。我建议添加一个(blur)="onTouchedCallback()"
到您的ControlValueAccessor,它应该可以工作。