说我有这个模板:
<div class="main__container">
<ng-template #test></ng-template>
<ng-template #test2></ng-template>
</div>
我通过以下方式检索对所有TemplateRef
的引用:
@ViewChildren(TemplateRef)
private templates;
对于所有这些,我如何检索相关变量的名称?所以&#34;测试&#34;对于第一个模板和&#34; test2&#34;对于另一个。我绝对不想使用变量,如果可以使用ng-template
属性,那就可以了。我尝试使用TemplateRef
,ViewContainerRef
和ElementRef
,但每次都会返回对comment
元素的引用。
答案 0 :(得分:1)
我设法使用TemplateRef的私有API来做到这一点。这是我目前使用的功能:
@ContentChildren(TemplateRef) templates: QueryList<TemplateRef<any>>;
getTemplate(id: string): TemplateRef<any> {
// FIXME: Should not use private API...
return this.templates ? this.templates.find((template: any) =>
template._def.references[id]) : null;
}
但这不适用于生产版本,实际上我发现你的帖子正在寻找另一个解决方案,如果我找到某些内容或者向Angular github提交功能请求,我会更新。 与此同时,我认为值得分享。
- 编辑 - 看起来很可能使用结构指令。
您将在本指南中了解到,星号(*)是一种方便的符号,字符串是微型语法,而不是通常的模板表达式。 Angular将这种符号放入围绕主机元素及其后代的标记
<ng-template>
中。每个结构指令都与该模板有所不同。
- 编辑2 - 好吧,它适用于检索TemplateRef的指令,但是目前我使用id将其注册到服务,我不再使用ViewChildren / ContentChildren了。使用* ngTemplateOutlet指令的My Component然后使用该服务检索TemplateRef。
这是指令源代码:
@Directive({
selector: '[formeTemplate]'
})
export class FormeTemplateDirective {
@Input('formeTemplate') templateId;
constructor(private host: TemplateRef<any>, private service: FormeTemplateService) { }
ngOnInit() {
this.service.register(this.templateId, this.host);
}
}
服务:
@Injectable()
export class FormeTemplateService {
private templates: Array<FormeTemplate>;
constructor() {
this.templates = new Array();
}
register(id: string, ref: TemplateRef<any>) {
this.templates.push(new FormeTemplate(id, ref));
}
getTemplateRef(templateId: string) : TemplateRef<any> {
let template = this.templates.find((template) => template.id === templateId);
return template ? template.ref : null;
}
}
答案 1 :(得分:1)
我还必须能够动态设置templateRef。目的是根据动态类型选择模板。
我的解决方案(https://stackblitz.com/edit/angular-dynamic-templateref):
@Directive({
selector: "[typeTemplate]"
})
export class TypeTemplateDirective {
@Input()
typeTemplate: string;
constructor(public templateRef: TemplateRef<any>) {}
}
@Component({
selector: "type-template",
template: `
<ng-container *ngTemplateOutlet="(template$ | async)"></ng-container>
<ng-template typeTemplate="typeA">Template for type A</ng-template>
<ng-template typeTemplate="typeB">Template for type B</ng-template>
`
})
export class TypeTemplateComponent implements AfterViewInit {
@ViewChildren(TypeTemplateDirective)
private typeTemplateDirectives: QueryList<TypeTemplateDirective>;
@Input()
set type(newType: string) {
this.type$.next(newType);
}
type$ = new BehaviorSubject<string>(null);
template$ = this.type$.pipe(
filter(() => !!this.typeTemplateDirectives),
map(
type =>
this.typeTemplateDirectives.find(
directive => directive.typeTemplate === type
).templateRef
)
);
ngAfterViewInit(): void {
this.type$.next(this.type$.getValue());
}
}
因此,当将新类型推入时,将使用正确的模板。
答案 2 :(得分:0)
答案 3 :(得分:0)
我有同样的问题。这个简单的示例说明了我的解决方案:
用法:
<app-my-component [templates]="{ highlight: highlightTemplate, italic: italicTemplate }" [useTemplate]="'highlight'">
<ng-template #highlightTemplate let-contentRef="contentRef">
<span class="highlighted-text"><ng-container *ngTemplateOutlet="contentRef"></ng-container></span>
</ng-template>
<ng-template #italicTemplate let-contentRef="contentRef">
<span class="font-italic"><ng-container *ngTemplateOutlet="contentRef"></ng-container></span>
</ng-template>
</app-my-component>
myComponent模板:
<div class="my-component">
<ng-template #contentRef>The content which is given to the customTemplate</ng-template>
<ng-container *ngTemplateOutlet="customTemplate; context: { contentRef: contentRef }" >
</ng-container>
</div>
类定义:
export class MyComponent {
@Input() private templates: any = {};
@Input() private useTemplate: string;
get customTemplate() {
return this.templates[this.useTemplate];
}
}