带有动态模板或 templateUrl 的 Angular 2/4 组件
Posted
技术标签:
【中文标题】带有动态模板或 templateUrl 的 Angular 2/4 组件【英文标题】:Angular 2/4 component with dynamic template or templateUrl 【发布时间】:2018-01-04 17:00:11 【问题描述】:我一直在尝试到处寻找解决方案。
我有一个具有不同“皮肤”的项目,它们基本上是不同的模板/Css 集。
我正在尝试让我的组件使用基于变量 THEME_DIR 的皮肤。
不幸的是,我找不到如何实现这一点。我在 angular.io 上查看了Dynamic Component Loader,但没有成功。
我也在这里看了一些答案,也没有成功。
有人有想法吗?
这是我迄今为止尝试过的:
import ComponentFactoryResolver, ViewContainerRef from '@angular/core';
// @Component(
// templateUrl: '../../assets/theme/'+THEME_DIR+'/login.template.html',
// )
export class LoginComponent implements, AfterViewInit
private log = Log.create('LoginPage');
constructor(private mzksLsRequestService: MzkLsRequestService,
private componentFactoryResolver: ComponentFactoryResolver,
public viewContainerRef: ViewContainerRef)
ngAfterViewInit()
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(new Component(
templateUrl: '../../assets/theme/default/login.template.html',
));
let viewContainerRef = this.viewContainerRef;
viewContainerRef.clear();
let componentRef = viewContainerRef.createComponent(componentFactory);
【问题讨论】:
【参考方案1】:你可以这样做:
import
Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef,
ViewContainerRef
from '@angular/core';
@Component(
selector: 'my-app',
template: `
<h1>Hello name</h1>
<ng-container #vc></ng-container>
`
)
export class AppComponent
@ViewChild('vc', read: ViewContainerRef) vc;
name = `Angular! v$VERSION.full`;
constructor(private _compiler: Compiler,
private _injector: Injector,
private _m: NgModuleRef<any>)
ngAfterViewInit()
const tmpCmp = Component(
moduleId: module.id, templateUrl: './e.component.html')(class
);
const tmpModule = NgModule(declarations: [tmpCmp])(class
);
this._compiler.compileModuleAndAllComponentsAsync(tmpModule)
.then((factories) =>
const f = factories.componentFactories[0];
const cmpRef = f.create(this._injector, [], null, this._m);
cmpRef.instance.name = 'dynamic';
this.vc.insert(cmpRef.hostView);
)
只要确保 URL 正确且模板已加载到客户端即可。
阅读Here is what you need to know about dynamic components in Angular了解更多详情。
【讨论】:
非常感谢。我想现在我的问题是 webpack 在编译模板时抱怨......我需要找到解决方法...... 刚刚尝试了全新的 Angular cli 项目,它在 webpack 上运行良好。您使用什么构建过程? 我使用离子样板。当我将变量放在模板路径中时它会抱怨(请参阅我的代码中的 THEME_DIR),因为它似乎找不到正确的路径 我明白了,不幸的是我对此并不熟悉。我认为您应该创建另一个问题,因为它与我回答的问题并不真正相关 如果有帮助,您也可以接受或投票赞成这个答案,谢谢【参考方案2】:我在尝试从服务器加载动态模板时遇到问题(我想进行安全检查,在提供 html 之前在服务器端进行翻译。
我在更改 webpack 配置后解决了这个问题。事实上,在完成ng eject
之后,它创建了一个webpack.config.js,其中包含一个.ts 加载器@ngtools/webpack
和:
new AotPlugin(
"mainPath": "main.ts",
"replaceExport": false,
"hostReplacementPaths":
"environments\\environment.ts": "environments\\environment.ts"
,
"exclude": [],
"tsConfigPath": "src/main/front/tsconfig.app.json",
"skipCodeGeneration": true
)
最后一个,是问题的根源。它涉及 AOT(提前)。根据文档: ngtools 在选项部分,它被提及:
跳过代码生成。可选,默认为 false。禁用代码 生成并且不要重构代码以引导。 这将 templateUrl: "string" 替换为 template: require("string")
如果您不希望您的 templateUrl 被 AOT 编译,我建议您删除 AotPlugin,并使用 ts-loader 而不是 @ngtools/webpack 参见:
ts-loader
ts 的规则如下所示:
test: /\.tsx?$/,
loader: 'ts-loader'
现在您可以根据需要从相对 URL 加载新模板。示例:
@Component(
selector : "custom-component",
templateUrl : "/my_custom_url_on_server"
)
export class CustomComponent
见Issue
【讨论】:
ng 弹出不再受支持。而且我不推荐这种解决方案。这个想法是让 Angular 编译模板【参考方案3】:从 Ivy(我认为)开始,我们可以在 templateUrl 中使用静态变量(例如环境)。 例如:
import environment from 'src/environments/environment';
@Component(
selector: 'home',
templateUrl: `./skins/$environment.skin/home.page.html`,
styleUrls: ['./skins/$environment.skin/home.page.scss']
)
【讨论】:
是的,这在编译时很酷,但是运行时呢?以上是关于带有动态模板或 templateUrl 的 Angular 2/4 组件的主要内容,如果未能解决你的问题,请参考以下文章