我已经实现了以下组件。它的工作和行为符合预期。然而,由于ControlValueAccessor
的实现对我来说是新的,我不得不follow a blog而不了解几个部分的更深层细节。所以这是一种“它有效,但为什么?!”的情况。
@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(...)
方法的第二和第三行,据我所知,没有任何事情发生。这些调用也始终由other blogs提出,因此我确信省略它们是不恰当的。但是,我不相信魔法,宁愿有一个具体的理由做事。
为什么在onChange(...)
中执行对onTouch(...)
和writeValue(...)
的调用很重要?会出现什么问题以及在什么情况下可以预期?
作为一项副作用,我还试图评论the other methods并发现当我移除setDisabledState(...)
时我无法告诉任何香蕉。什么时候可以预期会导致问题?是否真的需要实现(我在括号前后看到带有问号的版本,参数如此:setDisabledState?(state: boolean): void { }
,但也像这样:setDisabledState(state: boolean)?: void { }
)。
答案 0 :(得分:8)
阅读这篇文章,详细解释了ControlValueAccessor
:
如果组件应该用作Angular表单的一部分,通常需要在组件上实现ControlValueAcceessor
接口。
我注释掉了writeValue(...)方法的第二行和第三行 而且,据我所知,没有任何事情发生。
这可能是因为您没有应用将formControl
链接到自定义输入组件的任何表单指令 - ngModel
或FormControl
。 FormControl
使用writeValue
InputComponent
方法进行通信。
以下是我在上面引用的文章中的图片:
writeValue
formControl
方法用于将值设置为本机表单控件。 registerOnChange
使用formControl
方法来注册每次更新本机表单控件时都会触发的回调。 registerOnTouched
方法用于指示用户与控件进行交互。
为什么执行对onChange(...)的调用很重要 writeValue(...)中的onTouch(...)?什么会出错,在什么地方 情况可以预期吗?
这是实现ControlValueAcceessor
的自定义控件通知Angular FormControl
输入中的值已更改或用户与控件交互的机制。
...发现我不能告诉任何香蕉 删除了setDisabledState(...)......是否真的需要实现?
如界面中所指定,当控件状态更改为“DISABLED”或从“DISABLED”更改时,此函数将由表单API调用。根据值,它应启用或禁用适当的DOM元素。
如果您希望在关联的FormControl
的状态变为disabled
时收到通知,然后您可以执行某些自定义逻辑(例如,禁用您的输入组件),则需要实现它。
答案 1 :(得分:1)
我不认为被接受的答案能以简洁的方式回答最核心的问题:
为什么在writeValue(...)中执行对onChange(...)和onTouch(...)的调用很重要?
不是。您不需要需要在writeValue中调用onChange。这不是预期的用法(请参见下面的文档链接)。
出什么问题了,在什么情况下可以预见?
没什么可出错的。详细的答案:
如果您要从onChange
内部呼叫writeValue
,您会注意到:
registerOnChange
)。emitModelToViewChange = false
来避免递归调用writeValue),它会使用您从模型中获得的值(刚收到的值)进行更新。换句话说,除非您依靠您的组件以某种方式立即更改其在writeValue中接收的值,然后将这些更改传递给您的模型,但仅在 second / em>和更高版本的writeValue调用,可以安全地不从writeValue调用onChange。