在Angular中实现ControlValueAccessor时,为什么需要在writeValue中调用onChange和onTouch?
我已经实现了以下组件。它的工作和行为符合预期。然而,由于在Angular中实现ControlValueAccessor时,为什么需要在writeValue中调用onChange和onTouch?,angular,typescript,custom-component,Angular,Typescript,Custom Component,我已经实现了以下组件。它的工作和行为符合预期。然而,由于ControlValueAccessor的实现对我来说是新的,因此我不得不在不了解几个部分的更深层细节的情况下进行修改。所以这是一种“它有效,但为什么?!”的情况 @Component({ selector: ..., templateUrl: ..., styleUrls: ..., providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forw
ControlValueAccessor
的实现对我来说是新的,因此我不得不在不了解几个部分的更深层细节的情况下进行修改。所以这是一种“它有效,但为什么?!”的情况
@Component({ selector: ..., templateUrl: ..., styleUrls: ...,
providers: [{ provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputTextComponent),
multi: true }]
})
export class InputComponent implements ControlValueAccessor {
constructor() { }
@Input() info: string;
onChange: any = () => { }
onTouch: any = () => { }
writeValue(input: any): void {
this.info.value = input;
// this.onChange(input);
// this.onTouch();
}
registerOnChange(_: any): void { this.onChange = _; }
registerOnTouched(_: any): void { this.onTouch = _; }
setDisabledState?(state: boolean): void { }
onEdit(value: string): void { this.onChange(value); }
}
当我让它工作时,我注释掉了writeValue(…)
方法的第二行和第三行,据我所知,没有任何东西坏掉。这些电话也一直是由建议的,所以我相信省略它们是不合适的。然而,我不相信魔法,我更喜欢有一个具体的理由去做事情
为什么在writeValue(…)
中执行对onChange(…)
和onTouch(…)
的调用很重要?什么会出错?在什么情况下可以预期
作为一项附带任务,我还尝试注释掉,发现当我删除
setDisabledState(…)
时,我看不出有什么事情变得疯狂。什么时候会出现问题?它真的需要实现吗(我见过在括号前后都带有问号的版本,参数如下:setDisabledState?(状态:boolean):void{}
,但也像这样:setDisabledState(状态:boolean)?:void{}
).阅读这篇文章,详细解释ControlValueAccessor
:
ControlValueAcceessor
接口
我注释掉了writeValue(…)方法的第二行和第三行
而且,据我所知,什么也没破
这可能是因为您没有应用任何将formControl
链接到自定义输入组件的表单指令-formControl
或ngModel
。FormControl
使用InputComponent
的writeValue
方法进行通信
下面是我上面提到的文章中的图片:
formControl
使用writeValue
方法将值设置为本机表单控件。formControl
使用registerChange
方法注册回调,该回调预计在每次更新本机表单控件时都会触发。方法用于指示用户与控件交互
为什么执行对onChange(…)的调用和
onTouch(…)的书面值(…)?什么会出错,在什么情况下
情况如何
这是实现ControlValueAcceessor
的自定义控件通知Angular的FormControl
输入中的值已更改或用户与控件交互的机制
…发现当我离开时我什么都说不出来
删除了setDisabledState(…)…是否真的需要实现它
如接口中所指定,当控件状态更改为“禁用”或从“禁用”更改为“禁用”时,forms API将调用此函数。根据该值,它应该启用或禁用相应的DOM元素。
如果您希望在关联的FormControl
的状态变为disabled
时收到通知,然后您可以执行一些自定义逻辑(例如,禁用您的输入组件),则需要实现它。我不认为公认的答案以简洁的方式回答了最核心的问题:
为什么在writeValue(…)中执行对onChange(…)和onTouch(…)的调用很重要
事实并非如此。您不需要在writeValue中调用onChange。它不是预期用途(请参阅下面的文档链接)
什么会出错?在什么情况下可以预期
别指望出什么差错。详细回答:
如果要从内部调用onChange
,您会注意到:
- 第一个onChange调用什么都不做。这是因为在首次调用writeValue时,onChange回调尚未注册(即未调用registerChange
)
emitModelToViewChange=false
以避免递归调用writeValue)请参阅此处文档中的示例:您如何使用此组件?您是否阅读了?
为什么在writeValue(…)中执行对onChange(…)和onTouch(…)的调用很重要
你在哪里看到的?@yurzui,这里可能指的是@angolarindepth.com,我认为他指的是这个伟大的答案。不过有两次跟进#1如果我已经注册了onChange()
,但没有从writeValue()
调用它(只将值设置为backing字段,而没有将其传播到onChange()
),我仍然会将值获取到父组件中的表单组。那么现在什么不起作用了?我看不见。你有没有一个明确的例子来说明什么是不可行的#2我见过setDisableState()
没有问号,方法名称后面有问号,括号后面有问号。这是相同的意思吗?这是怎么回事?@Donkeybana,请阅读我引用的文章,如果你在那之后仍然有问题,请创建一个stackblitz演示,并让我知道文章中有什么不清楚的地方,你必须调用onChange