简体   繁体   English

如何使用templateRef?

[英]How to use templateRef?

I am trying to find a way to dynamically construct a template in Angular2. 我试图找到一种在Angular2中动态构建模板的方法。 I was thinking templateRef might provide a way to do this. 我在想templateRef可能会提供一种方法来做到这一点。 But I could be wrong. 但我可能是错的。

I found an example of templateRef being used here. 我在这里找到了一个templateRef的例子。

I was looking at templateRef in this example. 我在这个例子中看着templateRef。 I noticed the syntax is [ng-for-template] I also tried [ngForTemplate] cause I know this has changed recently. 我注意到语法是[ng-for-template]我也试过[ngForTemplate]因为我知道最近这个改变了。

So at the moment I have this: 所以此刻我有这个:

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);
    }
}

This example throws an error: 此示例引发错误:

Can't bind to 'ngForTemplate' since it isn't a known native property 无法绑定到'ngForTemplate',因为它不是已知的本机属性

So firstly I am wondering. 所以首先我想知道。 What is the right way to do this? 这样做的正确方法是什么? The docs don't provide any examples. 文档没有提供任何示例。

Secondly, is there a good way I can add new template logic to my template or dynamically construct a template? 其次,有没有一种方法可以将新的模板逻辑添加到我的模板或动态构建模板? The structure of the application can be a very large amount of different structural combinations. 应用的结构可以是非常大量的不同结构组合。 So if possible I would like to see if there is a way I can do this without having a huge template with a bunch of different ngIf and ngSwitch statements.. 所以,如果可能的话,我想看看是否有一种方法可以做到这一点,而没有一个包含大量不同ngIf和ngSwitch语句的巨大模板。

My question is really the first part about templateRef. 我的问题实际上是关于templateRef的第一部分。 But any help or suggestions on the second part is appreciated. 但是对第二部分的任何帮助或建议表示赞赏。

Creating your own template directive it's not difficult, you have to understand two main things 创建自己的模板指令并不困难,您必须了解两个主要内容

  • TemplateRef contains what's inside your <template> tag TemplateRef包含<template>标签内的内容
  • ViewContainerRef as commented by Gunter, holds the template's view and will let you to embed what's inside the template into the view itself. 由Gunter评论的ViewContainerRef保存模板的视图,并允许您将模板中的内容嵌入到视图本身中。

I will use an example I have when I tried to solve this issue , my approach is not the best for that, but it will work for explaining how it works. 我将使用一个例子,当我试图解决这个问题时 ,我的方法不是最好的,但它可以解释它是如何工作的。

I want to clarify too that you can use any attribute for your templates, even if they're already used by builtin directives (obviously this is not a good idea, but you can do it). 我想澄清你可以使用任何属性作为模板,即使它们已被内置指令使用(显然这不是一个好主意,但你可以这样做)。

Consider my approach for ngIfIn (my poor approach) 考虑我的ngIfIn方法(我的方法不好)

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

We have here two templates using two inputs each ngIfIn and ngIfValue , so I need my directive to grab the template by these two inputs and get their values too, so it would look like this 我们这里有两个模板,每个模板使用两个输入,每个ngIfInngIfValue ,所以我需要我的指令通过这两个输入来获取模板并获取它们的值,所以它看起来像这样

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

First I need to inject the two classes I mentioned above 首先,我需要注入上面提到的两个类

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

I also need to cache the values I'm passing through the inputs 我还需要缓存我通过输入的值

  _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;
  }

In my case I depend on these two values, I could have my logic in ngOnInit but that would run once and wouldn't listen for changes in any of the inputs, so I put the logic in ngOnChanges . 在我的情况下,我依赖于这两个值,我可以在ngOnInit使用我的逻辑,但是它会运行一次并且不会监听任何输入中的更改,因此我将逻辑放在ngOnChanges Remember that ngOnChanges is called right after the data-bound properties have been checked and before view and content children are checked if at least one of them has changed (copy and paste from the docs). 请记住, 在检查了数据绑定属性之后,在检查视图和内容子项之前,如果其中至少有一个已更改 (从文档复制和粘贴), ngOnChanges 调用 ngOnChanges

Now I basically copy & paste NgIf logic (not so complex, but similar) 现在我基本上复制并粘贴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();
    }
  }

As you see it's not that complicated : Grab a TemplateRef, grab a ViewContainerRef, do some logic and embed the TemplateRef in the view using ViewContainerRef. 如你所见,它并不复杂:抓住TemplateRef,抓取一个ViewContainerRef,做一些逻辑并使用ViewContainerRef将TemplateRef嵌入到视图中。

Hopefully I made myself clear and I made how to use them clear enough also. 希望我清楚自己,并且我也明确了如何使用它们。 Here's a plnkr with the example I explained. 这里有一个plnkr与我解释的例子。

ngForTemplate is only supported with ngFor ngForTemplate仅与支持ngFor

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

or 要么

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

not on a plain template. 不是简单的模板。 It is an @Input() on the NgFor directive 它是NgFor指令@Input()

Another way to use TemplateRef 另一种使用TemplateRef

If you have a reference to ViewContainerRef you can use it to "stamp" the template 如果您有对ViewContainerRef的引用,则可以使用它来“标记”模板

constructor(private _viewContainer: ViewContainerRef) { }

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM