Creating/Fetching 指令中的 TemplateRef

Creating/Fetching a TemplateRef from within a directive

我正在尝试创建一个插入 TemplateRef 的(结构)指令,但是 TemplateRef 的定义 "somewhere else"。

上下文

有时我想插入任意内容 现有元素中,但是出于 DOM 原因,重要的是它不是组件(虽然是类似属性的组件没问题)。

示例:

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

现在,我想做同样的事情,但将 2 行插入到我的 table 中。所以我希望做这样的事情:

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

问题是:

问题

我怎么能在结构指令中得到一个 TemplateRef,但它不是由指令的调用者传入的?

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

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

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

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

所以诀窍是使用 templateRef(示例中的 TemplatesComponent)创建组件,然后创建该组件(通过 viewContainerRef.createComponent)并访问 templateRef。