【问题标题】:Angular how to global / application scope templateAngular如何全局/应用范围模板
【发布时间】:2021-05-03 06:14:44
【问题描述】:

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

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

我试图提取这部分

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

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

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

提前致谢,

沙巴

【问题讨论】:

  • app.component.html 不是应用程序范围的模板,它只是默认的应用程序入口点。为了您的使用,您可以创建一个指令来添加这些属性并将其添加到任何必需的元素中?
  • 对不起,我没明白,属性是固定的,它的数据来自 json
  • 然后让你的模板成为它自己的组件,并将它需要的任何值作为@Input 属性传递。如果没有您当前如何使用该模板的详细信息,很难理解您的用例在这里是什么,因此我们可以看到您试图避免什么。
  • 好的,它需要一个自己的组件,另一方面意味着我们不能有全局模板。 (将其放入应用程序范围 html 会容易得多)

标签: angular templates reusability


【解决方案1】:

我知道这是一个老问题,但这是我多年来在 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>

【讨论】:

  • 谢谢先生 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 2017-05-22
相关资源
最近更新 更多