-1

我正在 NativeScript 和 Angular 中构建自动完成功能(这个问题也适用于纯 Angular)。

标记看起来像这样:

<StackLayout>
<TextField #keywords [hint]="options?.hint" [(ngModel)]="occupation"
    (textChange)="keywordsInputChange$.next(keywords.text)">
</TextField>
<ng-container *ngTemplateOutlet="parentTemplate"></ng-container>

<ScrollView orientation="vertical" height="200" *ngIf="dataItems?.length > 0" class="m-r-16 m-l-16 search-view">
    <ListView [items]="dataItems" (itemTap)="onItemTap($event)">
        <ng-template let-item="item">
            ...
        </ng-template>
    </ListView>
</ScrollView>

它将从外部使用:

<px-lookup (selected)="onOccupationSelected($event)" [options]="occupationLookupOptions">
    <ng-template let-item>
         <StackLayout class="search-item" backgroundColor="red">
               <Label [text]="item.text"></Label>
         </StackLayout>
    </ng-template>
</px-lookup>

如您所见,我想将自定义模板传递给 ListView 将使用的查找。我正在检索这样的模板

@ContentChild(TemplateRef, { static: false }) parentTemplate: TemplateRef<any>;

我可以通过定义在查找中毫无问题地渲染它

<ng-container *ngTemplateOutlet="parentTemplate; context: { $implicit: item }"></ng-container>

但是,当我尝试将其放入也需要模板的 LietView 时,我无法使其正常工作。我收到类似“错误:在列表模板中找不到合适的视图!嵌套级别:0' 任一项目都呈现为 [Object object]

我已经尝试了这些选项:

<ListView [items]="dataItems" (itemTap)="onItemTap($event)">
        1. Option ===> <ng-container *ngTemplateOutlet="parentTemplate"></ng-container> -->

        2. Option ===><ng-content></ng-content>

        3. Option ===> <ng-template let-item="item"> (top template that is required by ListView)
            <ng-container *ngTemplateOutlet="parentTemplate; context: { $implicit: item }"></ng-container> (Tried to render another template with current one by passing item down the pipe)
        </ng-template>
    </ListView>

有人知道我如何实现这一点吗?

谢谢

4

1 回答 1

0

关键是通过利用 TemplateRef 的依赖注入来创建一个指令来存储模板的 ref。

首先是指令:

// my-template.directive.ts

@Directive({ selector: '[myTemplate]' })
export class MyTemplateDirective  {
  @Input('myTemplate') type: string;

  constructor(public template: TemplateRef<any>) {}
}

(请注意,虽然type在这种简单的情况下没有使用该属性,但对于多个嵌套模板,它是必要的)

之后,在自动完成组件中,您使用该指令查找内容子项,如下所示:

// autocomplete.component.ts

@ContentChild(MyTemplateDirective, { static: false }) set setTemplate(value: MyTemplateDirective) {
   // for multiple templates you could implement logic using value.type

   // for example:
   // this.parentTemplates[value.type] = value.template

   this.parentTemplate = value.template;
};

并在模板中

// autocomplete.component.html
// Basically your Option 3

<ListView [items]="dataItems" (itemTap)="onItemTap($event)">   
  <ng-template let-item="item">
     <ng-container *ngTemplateOutlet="parentTemplate; context: { $implicit: item }"></ng-container>
  </ng-template>
</ListView>

那么你会像这样使用它:

<px-lookup (selected)="onOccupationSelected($event)" [options]="occupationLookupOptions">
    <ng-template let-item myTemplate="pxLookupElem">
         <StackLayout class="search-item" backgroundColor="red">
               <Label [text]="item.text"></Label>
         </StackLayout>
    </ng-template>
</px-lookup>
于 2020-04-01T09:46:38.380 回答