Angular 如何全局/应用范围模板
Angular how to global / application scope template
我需要在很多组件中重复使用参数化菜单模板来构建本地菜单
<ng-template #menubutton let-link="link" let-icon="icon" let-text="text" ...>
... does magic :)
</ng-template>
我试着提取这部分
- 进入可注入的通用菜单组件
- 添加到 app.component.html
但不起作用,也没有任何错误。
请撇开这个菜单解决方案很差,因为这个问题可以概括:我们如何制作应用程序范围模板?
提前致谢,
乔巴
我知道这是一个老问题,但这是我多年来在 Angular 项目中的做法。
我们需要 TemplateRef
个实例的简单映射:
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);
}
}
以及为模板分配键的指令:
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);
}
}
然后我们将全局模板放在app组件模板中:
<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>
以及用法:
<ng-container *ngTemplateOutlet="templateStore.get('avatar'); context: {$implicit: currentUser}"></ng-container>
这里的不便之处在于我们需要将 TemplateStore
注入到每个使用它的组件中。由于在我的 Angular 项目中,所有组件都继承了一个基础 class,我们可以通过在基础 class 中放入这样的方法来避免注入:
public template(key: string): TemplateRef<any> {
return AppContext.current.templateStore.get(key);
}
AppContext.current
是一个全局对象,它包含对 TemplateStore
的引用。所以用法变成:
<ng-container *ngTemplateOutlet="template('avatar'); context: {$implicit: currentUser}"></ng-container>
我需要在很多组件中重复使用参数化菜单模板来构建本地菜单
<ng-template #menubutton let-link="link" let-icon="icon" let-text="text" ...>
... does magic :)
</ng-template>
我试着提取这部分
- 进入可注入的通用菜单组件
- 添加到 app.component.html
但不起作用,也没有任何错误。
请撇开这个菜单解决方案很差,因为这个问题可以概括:我们如何制作应用程序范围模板?
提前致谢,
乔巴
我知道这是一个老问题,但这是我多年来在 Angular 项目中的做法。
我们需要 TemplateRef
个实例的简单映射:
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);
}
}
以及为模板分配键的指令:
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);
}
}
然后我们将全局模板放在app组件模板中:
<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>
以及用法:
<ng-container *ngTemplateOutlet="templateStore.get('avatar'); context: {$implicit: currentUser}"></ng-container>
这里的不便之处在于我们需要将 TemplateStore
注入到每个使用它的组件中。由于在我的 Angular 项目中,所有组件都继承了一个基础 class,我们可以通过在基础 class 中放入这样的方法来避免注入:
public template(key: string): TemplateRef<any> {
return AppContext.current.templateStore.get(key);
}
AppContext.current
是一个全局对象,它包含对 TemplateStore
的引用。所以用法变成:
<ng-container *ngTemplateOutlet="template('avatar'); context: {$implicit: currentUser}"></ng-container>