使用内联模板嵌入组件

Component transclude with inline template

我正在使用 Angular 2-rc3 并且有一个 Component,我想应用嵌入,只是方式有点不同。这是我的组件:

import { Component, Input } from '@angular/core';

@Component({
    selector: 'my-list',
    template: `<ul>
        <li *ngFor="let item of data">
            -- insert template here --
            <ng-content></ng-content>
        </li>
    </ul>`
})
export class MyListComponent {
    @Input() data: any[];
}

我是这样使用的:

<my-list [data]="cars">
    <div>{{item.make | uppercase}}</div>
</my-list>

如您所见,我正在尝试定义一个将由我的组件使用的内联模板。现在这是非常错误的。首先,一个数据绑定异常表明它 can't read property 'make' of undefined。它试图从我周围的组件中读取 item.make,而不是 MyListComponent。但即使我现在暂时禁用它:

<my-list [data]="cars">
    <div>{item.make | uppercase}</div>
</my-list>

然后出现第二个问题:

-- insert template here --
-- insert template here --
-- insert template here --
-- insert template here --
{item.make | uppercase}

所以 Angular 实际上并没有复制模板以供在 *ngFor 中使用,它只是绑定元素,它们最终与最后一项相关联。

如何让它工作?

我在 AngularJS 中遇到了同样的问题,其中 petebacondarwin posted a solution to manipulate the DOM through compile,这很好。通过在我的组件中注入 ElementRef,我也有 Angular 2 这个选项,但是!一个很大的区别是 AngularJS 中的 compile 在数据绑定之前关闭,这意味着在模板中使用 {{item.make}} 没有问题。对于 Angular 2,这似乎是行不通的,因为 {{item}} 是预先解析的。那么最好的方法是什么?使用略有不同的符号 [[item]] 和字符串替换整个东西似乎不是最优雅的方式......

提前致谢!

// 编辑:这是重现问题的 Plnkr

  • <ng-content>*ngFor 中不起作用,因此

    <li *ngFor="let item of data">
        -- insert template here --
        <ng-content></ng-content>
    </li>
    

不会做任何有意义的事情。一切都将被嵌入到第一个 <ng-content>

https://github.com/angular/angular/issues/8563 可能会解决您的一些需求。

  • 可能是一种方法,可以像您在问题中展示的那样做类似的事情。
    它要求您的组件的用户将内容包装在 <template> 标记中。

拼写ngForTemplate方法:

(从 Angular 4 开始,该元素现在称为 <ng-template>。)

  1. 在外部和内部组件中使用 <template> 标签,而不是 <ng-content>

  2. <li>移到了app.componenthtml,这个组件上的<template>有一个特殊的'let-' 引用内部组件中迭代变量的属性:

    <my-list [data]="cars">
      <template let-item>
        <li>
          <div>{{item.make | uppercase}}</div>
        </li>
      </template>
    </my-list>
    
  3. 内部组件也有 <template> 并使用 ngFor 的变体,如下所示:

    <ul>
        <template #items ngFor [ngForOf]="data" [ngForTemplate]="tmpl">
            -- insert template here --
        </template>
    </ul>
    
  4. 需要在组件代码中获取分配给ngForTemplate属性的'tmpl'变量:

    export class MyListComponent {
        @Input() data: any[];
        @ContentChild(TemplateRef) tmpl: TemplateRef;
    }
    
  5. @ContentChild和TemplateRef是angular位,需要导入

    import { Component, Input, ContentChild, TemplateRef } from '@angular/core';
    

请在此处查看包含这些更改的 plunkr 的分支 plnkr

对于您所述的问题,这不是最令人满意的解决方案,因为您将数据传递到列表中,所以您最好在外部使用 ngFor。另外,附加内容(文字“-- 在此处插入模板 --”)被删除,因此您想要显示它也必须在外部模板上。

我可以看到在内部组件中提供迭代(比如从服务调用)并且可能在代码中对模板进行一些操作时它可能很有用。