Reputation: 327
I need to reuse a parameterized menu template in many components to build up the local menu
<ng-template #menubutton let-link="link" let-icon="icon" let-text="text" ...>
... does magic :)
</ng-template>
I tried to extract this part
but doesn't work and no any error.
pls put aside that this menu solution is very poor because the question can be generalized: how can we make application scope templates ?
Thanks in advance,
Csaba
Upvotes: 0
Views: 1382
Reputation: 185
I know this is an old question but here's how I do it in my Angular project for years.
We need a simple map of TemplateRef
instances:
import { TemplateRef } from "@angular/core";
export class TemplateStore {
private templates: Map<string, TemplateRef<any>> = new Map<string, TemplateRef<any>>();
public add(key: string, template: TemplateRef<any>): void {
// The argument validation is omitted for brevity
this.templates.set(key, template);
}
public get(key: string): TemplateRef<any> {
return this.templates.get(key);
}
}
And a directive that assigns a key to templates:
import { Directive, Input, TemplateRef } from "@angular/core";
import { TemplateStore } from "./template-store";
@Directive({
selector: "[appTemplateKey]"
})
export class TemplateKey {
constructor(
private readonly template: TemplateRef<any>,
private readonly templateStore: TemplateStore
) { }
@Input("appTemplateKey")
public set key(value: string) {
this.templateStore.add(value, this.template);
}
}
Then we put the global templates in the app component template:
<ng-template appTemplateKey="avatar" let-user>
<a routerLink="/{{user.id}}" aria-hidden="true" tabindex="-1">
<img [src]="user.pictureUrl" alt="" loading="lazy">
</a>
</ng-template>
And the usage:
<ng-container *ngTemplateOutlet="templateStore.get('avatar'); context: {$implicit: currentUser}"></ng-container>
The inconvinience here is that we need to inject the TemplateStore
into every component that uses it. Since in my Angular project all the components inherit a base class, we can avoid the injection by putting in the base class a method like this:
public template(key: string): TemplateRef<any> {
return AppContext.current.templateStore.get(key);
}
The AppContext.current
is a global object that holds a reference to the TemplateStore
. So the usage become:
<ng-container *ngTemplateOutlet="template('avatar'); context: {$implicit: currentUser}"></ng-container>
Upvotes: 2