从指令中创建/获取 TemplateRef

Posted

技术标签:

【中文标题】从指令中创建/获取 TemplateRef【英文标题】:Creating/Fetching a TemplateRef from within a directive 【发布时间】:2020-01-01 19:15:23 【问题描述】:

我正在尝试创建一个插入 TemplateRef 的(结构)指令,但其中 TemplateRef 被定义为“其他地方”。

上下文

我有时想将任意内容插入一个现有元素,但出于 DOM 的原因,重要的是它不是一个组件(尽管类似属性的组件也可以)。

例子:

<table>
  <tr my-row-component></tr>
</table>
@Component(
  selector: 'tr[my-row-component]'
  template: `<td>...</td><td>...</td><td>...</td>...`
)

现在从这里开始,我想做同样的事情,但在我的表中插入 2 行。所以我希望做类似的事情:

<table>
  <ng-template myTwoRowsDirective></ng-template>
</table>

问题是:

我有一个结构指令,这样我就可以插入我想要的代码 我需要一个组件,这样我就可以编写要插入到指令中的 html

问题

我如何在结构指令中获得TemplateRef,但指令的调用者没有传入?

@Directive(selector: '[myTwoRowsDirective]')
export class MyTwoRowsDirective 
  constructor(
      viewContainerRef: ViewContainerRef) 
    const templateRef = ???; // Reference to template defined elswhere
    viewContainerRef.createEmbeddedView(templateRef, this.context);
  

【问题讨论】:

【参考方案1】:

不知道这是否是推荐的做法,但这似乎可行(虽然尚未在您的用例中测试过):

@Component(
  template: `
    <ng-template #helloRef>
      <h1>hello</h1>
    </ng-template>
  `
)
export class TemplatesComponent 
  @ViewChild('helloRef',  static: true ) public helloRef: TemplateRef<any>;


@Directive(
  selector: 'whatever-component'
)
export class CustomizeWhateverDirective implements AfterViewInit 
  private static componentRef: ComponentRef<TemplatesComponent>;

  constructor(
    @Self() private whatever: WhateverComponent,
    private resolver: ComponentFactoryResolver,
    private _vcr: ViewContainerRef
  ) 

  ngAfterViewInit(): void 
    const componentRef = this.getComponentRef();

    const helloRef = componentRef.instance.helloRef;
    this.whatever.helloTemplate = helloRef;
  

  private getComponentRef() 
    if (!CustomizeWhateverDirective.componentRef) 
      const factory = this.resolver.resolveComponentFactory(TemplatesComponent);
      CustomizeWhateverDirective.componentRef = this._vcr.createComponent(factory);
    

    return CustomizeWhateverDirective.componentRef;
  

此代码设置我项目中所有任何组件的 helloTemplate 属性。

所以诀窍是拥有一个带有 templateRef 的组件(示例中为 TemplatesComponent),然后创建该组件(通过 viewContainerRef.createComponent)并访问 templateRef。

【讨论】:

以上是关于从指令中创建/获取 TemplateRef的主要内容,如果未能解决你的问题,请参考以下文章

在打字稿中创建指令以显示角度加载进度

如何在 php 中创建干净的 url 从 mysql 获取数据?

为啥 ngfor 指令不起作用,尽管我在 Typescript 类中创建了正确的对象

在 Angular 指令中创建过滤器

在 Angular 6 中创建用于跨字段验证(确认密码)的自定义指令

动态渲染嵌套组件(在父组件中创建)作为指令