从指令中创建/获取模板引用



我正在尝试创建一个插入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);
}
}

不知道这是否是推荐的做法,但这似乎有效(虽然还没有在你的用例上测试过(:

@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。

最新更新