如何让实验性的ngTemplateOutlet起作用?

26

我正在尝试在Angular2中构建一个列表组件,该组件从组件的用户处获取项目、列和项目字段模板。因此,我正在尝试使用ngTemplateOutletngOutletContext(据我所知是实验性的)。但我无法使其正常工作。

这里是一个简化的组件,演示了我的尝试:

<div *ngFor="let item of items>
  <span *ngFor="let column of columns>
    <template [ngOutletContext]="{ item: item }" 
              [ngTemplateOutlet]="column.templateRef"></template>
  </span>
</div>

这里是该组件的使用方法:

<my-component [items]="cars" [columns]="carColumns">
  <template #model>{{item.model}}</template>
  <template #color>{{item.color}}</template>
  <template #gearbox>{{item.gearbox}}</template>
</my-component>

这里是示例数据:

cars = [
  { model: "volvo", color: "blue", gearbox: "manual" },
  { model: "volvo", color: "yellow", gearbox: "manual" },
  { model: "ford", color: "blue", gearbox: "automatic" },
  { model: "mercedes", color: "silver", gearbox: "automatic" }
];

carColumns = [
  { templateRef: "model" },
  { templateRef: "color" },
  { templateRef: "gearbox" }
];

这里是一个 plunker 示例,根据 Günters 的评论调整了代码后重新现出了问题: https://plnkr.co/edit/jB6ueHyEKOjpFZjxpWEv?p=preview


1
你是否试图将 TemplateRef 作为字符串传递?一种方法是使用 https://plnkr.co/edit/3yM25cUVeP4fK0cxhpXp?p=preview - yurzui
另一种方法是使用 ContentChildren https://plnkr.co/edit/2Ohj12Gax6UaK6LJ5dwD?p=preview - yurzui
@yurzui 很有趣。你的版本是如何工作的,而我的不行?不,columns 需要是一个对象列表,因为我会传递额外的信息,比如标题以及它当前是否应该显示等。似乎你的 plunker 和我的唯一区别就是你把 columns 作为字符串列表传递了。 - Hampus
ngTemplateOutlet param should be TemplateRef instance but in your case it's string - yurzui
@yurzui,我不明白你想说什么。在你的(工作中的)plunker中,它也是一个字符串。似乎没有问题。我应该在哪里创建templateRef实例? - Hampus
1
在你的模板<template #model>中,model将是一个TemplateRef实例。如果您想在组件中将model用作TemplateRef,则应查看ViewChild(ViewChildren)https://dev59.com/VVkS5IYBdhLWcg3waWDD#39909203 还请参阅https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars - yurzui
3个回答

28

这就是你需要做的方式:

@Component({
  selector: 'my-component',
  template: `
    <div *ngFor="let item of items">
      <span *ngFor="let column of columns">
        <template [ngTemplateOutlet]="column.ref" [ngOutletContext]="{ item: item }"></template>
      </span>
    </div>`
})
export class MyComponent {
  @Input() items: any[];
  @Input() columns: any[];
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <my-component [items]="cars" [columns]="columns">
        <template #model let-item="item">{{item?.model}}</template>
        <template #color let-item="item">{{item?.color}}</template>
      </my-component>
    </div>`
})
export class App {
  @ViewChild('model') model;
  @ViewChild('color') color;
  cars = [
      { model: "volvo", color: "blue" },
      { model: "saab", color: "yellow" },
      { model: "ford", color: "green" },
      { model: "vw", color: "orange" }
    ];

  ngAfterContentInit() {
    this.columns = [
      { ref: this.model },
      { ref: this.color ]
    ];
  }
}

Plunker


2
非常感谢。我并没有离谱,但足够远,让我有冲动撞墙。 - Hampus
1
我很惊讶你需要明确地说“let-item =” item“。添加一个let解决了我遇到的类似问题。你会认为这是暗示的。 - Travis Parks
{ ref: this.color ] 这里不是括号,在4.0版本之后要改为<ng-template>。 - Wang Xiao
1
Plunkr已更新至5 https://plnkr.co/edit/HuQOYuNfyzAvQrXRlBLf?p=preview - IrishDubGuy

15

1
啊,明白了。但还是不起作用。现在我得到了 core.umd.js:3072 ORIGINAL EXCEPTION: templateRef.createEmbeddedView is not a function - Hampus
请提供一个 Plunker 以便重现问题。只有一些代码片段很难进行调试。 - Günter Zöchbauer
我添加了一个 Plunker。 - Hampus
1
和PatrickJane得出了相同的结论,但他在Plunker上更快。 - Günter Zöchbauer
2
无论如何感谢你的帮助。这不是一场比赛。 - Hampus
我只是不想让它看起来像我抄袭了这个 Plunker。 - Günter Zöchbauer

0

你可以不使用ngOutletContext来实现。你需要使用ng-template代替template。 以下代码适用于我:

app.component.html:

<div>
  <ng-template #c1>
    <app-child1></app-child1>
  </ng-template>
  <app-parent [templateChild1]="c1"></app-parent>
</div>

app-parent 是 app-component 的子组件。app-child 在 app-component 中声明为模板,该模板在 app-parent 中使用。

app.parent.html:

<p>
  <ng-template [ngTemplateOutlet]="templateChild1"></ng-template>
</p>

app.parent.ts:

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @Input() public templateChild1: TemplateRef<any>;

  public ngOnInit() {
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接