javascript - 如何在自动完成组件中显示不同的焦点值和模糊值

标签 javascript angular typescript angular-material

我正在尝试根据焦点/模糊自动完成输入显示不同的值。

假设我们有项目建议,其中每个项目都有 iddesc。我想按 iddesc 过滤项目。当我选择其中一个并且输入模糊时,应该显示 iddesc(例如 1 - item01)。

当焦点回到输入上时,它应该只显示 id(没有 desc),如果有任何关于该 id 的建议(比如 if 10那里应该建议 1010 | desc )。现在我必须强行删除 desc 才能返回到 id。事实并非如此。

感谢您的任何建议。

您可以尝试编辑this example

查看图像上的预期行为:

enter image description here

最佳答案

控制值访问器 (CVA)

ControlValueAccessor界面就是您要找的。

为什么?该接口(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):

  1. writeValue(obj: any): void
  2. registerOnChange(fn: any): void
  3. registerOnTouched(fn: any): void
  4. 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.onChangedthis.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/

相关文章:

javascript - 尝试从 "observable' s 链获取可观察性时出现错误”

reactjs - 使用 axios 拦截器和响应时出错

javascript - 第一次加载组件时 Angular 4 ngOnInit 不工作

javascript - 使用 Javascript 函数创建 DOJO 按钮会导致创建的按钮发生冲突

javascript - 为什么 Swiper 在 Angular 上不适合我?

javascript - Angular 2 : Send data from one component to other and act with the data

javascript - 如何创建具有一个可选属性的 typescript 泛型类型?

javascript - 在 typescript 中使用@waves/waves-crypto 在waves 区 block 链上创建加密地址时出错

javascript - 如何在模式中将社交媒体按钮作为标题

javascript - 如何创建 Mongoose Model 对象数组?