首页 > 解决方案 > Angular如何全局/应用范围模板

问题描述

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

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

我试图提取这部分

  1. 到一个可注入的公共菜单组件中
  2. 添加到 app.component.html

但不起作用,也没有任何错误。

请撇开这个菜单解决方案很差,因为这个问题可以概括:我们如何制作应用程序范围模板?

提前致谢,

乔巴

标签: angulartemplatesreusability

解决方案


我知道这是一个老问题,但这是我多年来在 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 项目中,所有组件都继承了一个基类,因此我们可以通过在基类中放入如下方法来避免注入:

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>

推荐阅读