【问题标题】:Angular Material Autocomplete Using An Array<Object>使用 Array<Object> 的角度材质自动完成
【发布时间】:2020-12-14 10:55:38
【问题描述】:

我有以下 Stackblitz: AutoComplete - StackBlitz

一旦用户选择一个选项,然后清除输入并开始输入,过滤就会停止工作。

用户如何选择一个选项并在只显示有效结果的地方开始输入?

【问题讨论】:

标签: angular filter autocomplete angular-material


【解决方案1】:

它停止工作,因为您在 rxjs 流中遇到错误。

value 可以是 stringoption 对象。您必须通过map 运算符正确映射它:

代替

.pipe(
  startWith(''),
  map(value => this._filter(value))
);

尝试以下方法:

.pipe(
  startWith(''),
  map(value => typeof value === 'string' ? value : value.address),
  map(address => address ? this._filter(address) : this.options.slice())
);

Forker Stackblitz

参见Angular material docs中的显示值自动完成示例

更新

OP 认为这个实现有问题:

为了方便起见,我再次分叉了您的按钮并添加了一个按钮。如果你 选择一个选项,单击继续,从邮政编码中退格“0”, 单击继续,将零添加回输入,单击继续。这 给你未定义的https://stackblitz.com/edit/angular-material-autocomplete-eg-4w15ki?file=app/autocomplete-filter-example.html

但是,如果您检查材料文档,它会按预期工作,因为 Angular 材料自动完成https://github.com/angular/components/issues/3334 中没有匹配选择或强制选择功能@

这意味着如果您正在键入并且键入的字符串与自动完成中的值完全匹配,那么 FormControl 的值将仍然是字符串而不是您所期望的对象。

为了强制它,您可以创建一个简单的指令,例如:

@Directive({
  selector: "[forceSelection]"
})
export class AutocompleteForceSelectionDirective implements AfterViewInit, OnDestroy {
  @Input() matAutocomplete: MatAutocomplete;

  @Input('forceSelection') key: string;

  private destroyed$ = new Subject();

  constructor(
    @Host() @Self() private autoCompleteTrigger: MatAutocompleteTrigger,
    private ngControl: NgControl
  ) {}

  ngAfterViewInit() {
    this.autoCompleteTrigger.panelClosingActions
      .pipe(
        filter(e => !e || !e.source),
        takeUntil(this.destroyed$)
      )
      .subscribe(e => {
        const selected = this.matAutocomplete.options
          .map(option => option.value)
          .find(option => (this.key ? option[this.key] : option) === this.ngControl.value);

        if (selected) {
          this.ngControl.control.setValue(selected);
        }
      });
  }

  ngOnDestroy() {
    this.destroyed$.next();
  }
}

并将其应用于您的输入

<input ... [matAutocomplete]="auto" forceSelection="address">

https://stackblitz.com/edit/angular-material-autocomplete-eg-lih2bo?file=app%2Fautocomplete-force-selection.directive.ts

【讨论】:

  • 这似乎行得通。虽然我会多玩一点以确保我理解,但我将其标记为答案。
  • 再看,当您选择一个选项时出现问题,然后退格输入地址的任何部分并手动重新输入而不选择选项this.myControl.value.id将返回undefined跨度>
  • 为了方便起见,我再次分叉了你的并添加了一个按钮。如果您选择一个选项,请单击继续,从邮政编码中退格“0”,单击继续,将零添加回输入,单击继续。这给了你undefinedstackblitz.com/edit/…
  • 我更新了答案。你可以查看这个演示stackblitz.com/edit/…
  • 1.感谢您写下我能够合并的内容,2。我不敢相信 Angular 没有更好的方法来做到这一点。 3. 我还剩下最后一件,那就是表单验证件。我将property.dirty &amp;&amp; property.errors?.required 添加到了一个div,但是关于在这种情况下选项不匹配时如何填充无效消息的任何建议(这将与所需消息分开,并且仅在字段脏时显示和字段没有违反所需的验证器)? - 也许是自定义验证器?
猜你喜欢
  • 1970-01-01
  • 2017-07-27
  • 2020-04-09
  • 2016-10-06
  • 1970-01-01
  • 2018-03-08
  • 2019-06-14
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多