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>
问题是:
- 我有一个结构指令,这样我就可以插入我想要的代码
- 我需要一个组件,这样我就可以写 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。
我正在尝试创建一个插入 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>
问题是:
- 我有一个结构指令,这样我就可以插入我想要的代码
- 我需要一个组件,这样我就可以写 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。