angular 内的 ngTemplateOutlet 材料自动完成仅使用默认选项呈现

ngTemplateOutlet inside angular materials autocomplete only renders with default option

我正在尝试使用材料自动完成和 ngTemplateOutlet 创建一组自定义模板,以切换我想使用哪个模板来显示结果(例如,如果有分组结果,它们将以不同于传统自动完成选项的方式显示)。

ngTemplateOutlet 似乎仅在提供默认选项时才呈现模板。如果没有至少一个 mat-option 存在,似乎无法将选项直接附加到 mat-autocomplete。理想情况下,唯一呈现的选项是从组件中获取的选项(在更复杂的示例中,以下代码很简单,但仍然会重现问题)。本质上,我正在寻找解决方法。

我已经尝试了所有我能想到的关于 ng-container 和模板的变体。

例如,模板为

<ng-template #default let-options="options">
  <mat-option *ngFor="let option of options" [value]="option">
  {{option}}
  </mat-option>
</ng-template>

这不会呈现任何自动完成选项

<mat-autocomplete #auto="matAutocomplete">
    <ng-container *ngTemplateOutlet="default; context:{options: options}"></ng-container>
</mat-autocomplete>

但是,在包含至少一个 mat-option 的情况下,这会呈现所有这些选项

<mat-autocomplete #auto="matAutocomplete">
    <mat-option>Test</mat-option>
    <ng-container *ngTemplateOutlet="default; context:{options: options}"></ng-container>
</mat-autocomplete>

这里有一个 stackblitz:https://stackblitz.com/edit/angular-bz45ae?file=app/autocomplete-simple-example.html

这与 mat-autocomplete 行为有关。它使用 @ContentChildren 访问 MatOptionQueryListmat-autocomplete 也有一个 ngAfterContentInit 挂钩,它在其中创建一个 ListKeyManger,管理项目列表中的活动选项,传递 QueryListMatOptions 的作为构造函数参数。可以看到here.

是的,那些 mat-option 被渲染了,但它仍然不能正常工作,你可以通过添加 optionSelected 侦听器来检查它:

<mat-autocomplete #auto="matAutoComplete" (optionSelected)="optionSelected($event)">

假设我们在组件的 optionSelected 方法中执行 console.log - 当您单击通过 ngTemplateOutlet 呈现的任何选项时,它不会被调用。 mat-autocomplete 无法访问此列表,因为此列表是另一个视图的一部分(ng-template 中的所有内容都是单独编译的视图定义)。

您可以创建一个可重复使用的组件,您将通过注入 FormGroupDirective.

传递一个 options 绑定和 link 它与父表单