Angular 如何全局/应用范围模板

Angular how to global / application scope template

我需要在很多组件中重复使用参数化菜单模板来构建本地菜单

<ng-template #menubutton let-link="link" let-icon="icon" let-text="text" ...>  
... does magic :)
</ng-template>

我试着提取这部分

  1. 进入可注入的通用菜单组件
  2. 添加到 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>