如何使用templateRef?

时间:2016-03-28 16:26:58

标签: javascript angular angular2-template

我试图找到一种在Angular2中动态构建模板的方法。我在想templateRef可能会提供一种方法来做到这一点。但我可能是错的。

I found an example of templateRef being used here.

我在这个例子中看了templateRef。我注意到语法是[ng-for-template]我也试过[ngForTemplate]因为我知道最近这已经改变了。

所以目前我有这个:

import {Component, TemplateRef} from 'angular2/core';

@Component({
    selector : 'body',
    template : `
        <template [ngForTemplate]="container">
            <div class="container"></div>
        </template>
    `
})

export class App
{
    @ContentChild(TemplateRef) container;

    constructor() {}

    ngAfterContentInit()
    {
        console.log(this);
    }
}

此示例引发错误:

Can't bind to 'ngForTemplate' since it isn't a known native property

所以首先我想知道。这样做的正确方法是什么? The docs don't provide any examples.

其次,有没有一种方法可以将新模板逻辑添加到我的模板或动态构建模板?应用的结构可以是非常大量的不同结构组合。所以,如果可能的话,我想看看是否有一种方法可以做到这一点,而不需要一个包含大量不同ngIf和ngSwitch语句的巨大模板。

我的问题实际上是关于templateRef的第一部分。但是对第二部分的任何帮助或建议表示赞赏。

2 个答案:

答案 0 :(得分:16)

创建自己的模板指令并不难,你必须了解两件主要的事情

  • TemplateRef包含<template>标记
  • 中的内容 由Gunter评论的
  • ViewContainerRef持有模板的视图,并允许您将模板中的内容嵌入到视图中。

我将使用我尝试解决此问题时的示例issue,我的方法不是最好的,但它可以解释它是如何工作的。

我还要澄清一下,你可以使用任何属性作为模板,即使它们已被内置指令使用(显然这不是一个好主意,但你可以这样做)。

考虑我对ngIfIn的方法(我的糟糕方法)

<template  [ngIfValue]="'make'" [ngIfIn]="obj">
  This will print
</template>
<template [ngIfValue]="'notExistingValue'" [ngIfIn]="obj">
  This won't print
</template>

我们这里有两个模板,每个模板使用两个输入ngIfInngIfValue,所以我需要我的指令通过这两个输入获取模板并获取它们的值,所以它看起来像这样< / p>

@Directive({
  selector : '[ngIfIn][ngIfValue]',
  inputs : ['ngIfIn', 'ngIfValue']
})

首先,我需要注入上面提到的两个类

constructor(private _vr: ViewContainerRef, private _tr: TemplateRef) {}

我还需要缓存I&#39; m通过输入的值

  _value: any;
  _obj: any;

  // Value passed through <template [ngIfValue]="'...'">
  set ngIfValue(value: any) {
    this._value = value;
  }

  // Value passed through <template [ngIfIn]="...">
  set ngIfIn(obj: any) {
    this._obj = obj;
  }

在我的情况下,我依赖于这两个值,我可以在ngOnInit中使用我的逻辑,但是它会运行一次并且不会监听任何输入中的更改,因此我将逻辑放入ngOnChanges。请记住,在检查了数据绑定属性之后,在检查了视图和内容子项之前,如果其中至少有一个已更改(从文档中复制并粘贴),则会立即调用ngOnChanges

现在我基本上复制&amp;粘贴NgIf逻辑(不那么复杂,但相似)

  // ngOnChanges so this gets re-evaluated when one of the inputs change its value
  ngOnChanges(changes) {
    if(this._value in this._obj) {

      // If the condition is true, we embed our template content (TemplateRef) into the view
      this._vr.createEmbeddedView(this._tr);
    } else {

      // If the condition is false we remove the content of the view
      this._vr.clear();
    }
  }

正如您所看到的那样并不复杂:抓住TemplateRef,抓住ViewContainerRef,做一些逻辑并使用ViewContainerRef将TemplateRef嵌入到视图中。

希望我清楚自己,并且我也明确地使用了它们。这是一个plnkr,我解释了这个例子。

答案 1 :(得分:4)

ngForTemplate仅受ngFor

支持
<template [ngFor] [ngForOf]="..." [ngForTemplate]="container"

<div *ngFor="..." [ngForTemplate]="container"

不在普通模板上。它是NgFor directive

上的@Input()

使用TemplateRef

的另一种方法

如果您引用了ViewContainerRef,则可以使用它来标记&#34;标记&#34;模板

constructor(private _viewContainer: ViewContainerRef) { }

ngOnInit() {
  this.childView = this._viewContainer.createEmbeddedView(this.templ);
  this.childView.setLocal('data', this.data);
}