我正在尝试根据焦点/模糊自动完成输入显示不同的值。
假设我们有项目建议,其中每个项目都有 id
和 desc
。我想按 id
和 desc
过滤项目。当我选择其中一个并且输入模糊时,应该显示 id
和 desc
(例如 1 - item01)。
当焦点回到输入上时,它应该只显示 id
(没有 desc
),如果有任何关于该 id
的建议(比如 if 10那里应该建议 1010 | desc )。现在我必须强行删除 desc
才能返回到 id
。事实并非如此。
感谢您的任何建议。
您可以尝试编辑this example
查看图像上的预期行为:
最佳答案
控制值访问器 (CVA)
ControlValueAccessor界面就是您要找的。p>
为什么?该接口(interface)将 DOM 与 Angular Form 分离,允许下拉显示和输入与表单实际使用的值不同。
您可以将自定义输入实现为单独的组件*并传入 FormControl。
以下是未经测试的Working Stackblitz
*Edit 3 - 我相信也可以将其作为指令来实现。请参阅 - Angular 2 Directive implementing ControlValueAccessor doesn't update 'touched' property on change
黑盒之外
您的 app.component.html 最终会像这样。
<form class="example-form">
<app-auto-special [users]="options" [formControl]="myControl"></app-auto-special>
</form>
app-auto-special 就像一个黑盒子,它只关心用户 ID。
我们可以 patchValue 或 setValue,它会做它的事情(在内部调用 writeValue)。如果我们与此组件交互,我们将获得 FormControl 值的用户 ID。
编辑 - 没有什么能阻止您传递整个用户对象。根据这个问题,我假设 OP 想要 id。
编辑 2 - 改为传递用户对象的示例 Working Stackbliz
黑盒内部
我们需要使用 NG_VALUE_ACCESSOR 将 app-auto-special 组件注册为 controlValueAccessor 的提供者。这是通过以下方式完成的:
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AutoSpecialComponent),
multi: true
}]
因此在黑盒内部我们实现了由 4 个方法组成的接口(interface):
-
writeValue(obj: any): void
-
registerOnChange(fn: any): void
-
registerOnTouched(fn: any): void
-
setDisabledState(isDisabled: boolean)?: void
这通常意味着以下样板文件:
export class AutoSpecialComponent implements ControlValueAccessor {
public _value: number;
public disabled: boolean;
onChanged: any = () => {};
onTouched: any = () => {};
/*
* ControlValueAccessor boilerplate
*
*/
writeValue(value): void {
this._value = value
}
registerOnChange(fn: any): void {
this.onChanged = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled
}
}
我们复制了 registerOnChange
提供的功能和 registerOnTouched
并在我们想要更新 formControl 值或它位于 touched 属性时调用这些副本( this.onChanged
和 this.onTouched
)。 setDisabledState
是可选的,writeValue
在初始化时或我们调用 patchValue
时被调用或 setValue
来自 parent 。
要设置 FormControl,我们调用 this.onChanged(some_value);
我们可以连接到各种事件 input
, focusin
, blur
, optionSelected
并决定分别发生什么:
- FormControl 值
- 显示哪些选项
- 输入的显示字符串应该是什么
这个答案附带一个警告,这是我完成的第一个 CVA 实现,所以我的基础不稳定。
额外的好处
- 单元测试 - 独立的 DOM 显示与表单
- 逻辑分离 - 父级不再饱和
资源
通过以下 youtube 视频了解更多信息 The Control Value Accessor | Jennifer Wadella
这伴随着以下 slides
关于javascript - 如何在自动完成组件中显示不同的焦点值和模糊值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57273454/