我正在制作一个可重用的Angular2组件,我希望用户能够指定一个模板字符串或templateUrl,然后该组件将通过属性或通过某种服务方法设置它。
在角1中,这很简单,我们可以这样做:
// somewhere else in app
myService.setTemplateUrl('path/to/template.html');
// directive definition
function myDirective(myService) {
return {
template: function(element, attrs) {
return attrs.templateUrl || myService.getTemplateUrl();
}
// ...
};
}这是如何在Angular2中实现的?
@Component({
selector: 'my-component',
template: '...' // cannot see `mySerivce` from here, nor access the element attributes
})
export class MyComponent {
constructor(private myService: MyService) {}
}虽然我的问题具体涉及如何实现动态模板,但更广泛的问题是是否可以从各个装饰器访问注入的依赖实例。
发布于 2016-02-26 09:43:14
所以我终于想出了一种用定制模板来做我想做的事情的方法。
我认为实际问题的答案必须是否,在装饰器中不能使用注入器。这是我对角质2的生命周期的理解。
对于那些感兴趣的人,下面是我为实现用户定义的自定义模板而提出的:
给定一个指令SimpleTimer,我们可以提供如下自定义模板:
<!-- app.ts template -->
<div *simpleTimer="#timer=timerApi">
<div class="time">{{ timer.getTime() }}</div>
<div class="controls">
<button (click)="timer.toggle()">Toggle</button>
<button (click)="timer.reset()">Reset</button>
</div>
</div>然后使用TemplateRef和ViewContainerRef注入器,如下所示:
// SimpleTimer.ts
constructor(private templateRef: TemplateRef,
private viewContainer: ViewContainerRef,
private cdr: ChangeDetectorRef) {}
ngOnInit() {
// we need to detach the change detector initially, to prevent a
// "changed after checked" error.
this.cdr.detach();
}
ngAfterViewInit() {
let view = this.viewContainer.createEmbeddedView(this.templateRef);
let api = {
toggle: () => this.toggle(),
reset: () => this.reset(),
getTime: () => this.getTime()
}
view.setLocal('timerApi', api);
setTimeout(() => this.cdr.reattach());
}想了解一下这是如何工作的,为什么要这样做,请看我写的关于这个话题的博客文章。。
发布于 2015-12-17 23:27:51
编辑:我刚刚注意到您的目的是访问DI。现在你不能,因为他们开得太晚了。这个答案的其余部分是做你问过的模板内容。
我对这个问题很感兴趣,所以我花了比我想象的更多的时间来研究这个问题。据我所知,目前还没有一种轻松的方法可以做到这一点。
你有三个主要选择:
1.使用*ng-如果使用已知组件
这是迄今为止解决这一问题的最简单方法。通过只有几个选项,您只能加载所需的组件。
<special *ngIf="!type">Default</special>
<special *ngIf="type == 'awesome'"> I'm Awesome </special>
<special *ngIf="type == 'admin'">Admin Only</special>Pros:轻松,模板语法。Cons:必须知道类型,当有许多选项时会变得很烦人
2.使用DynamicComponentLoader动态创建组件
这是毛茸茸的,而且相当先进。基本上,您可以根据传递的参数调用加载组件。这将允许您定义模板值,然后传递它以创建新组件。
这是一篇学习如何开始使用它的好文章。
下面是使用它来动态加载组件的人(超级黑客,捣乱asyncRouter)
Pros:解决这个问题的“角度”方式,超级灵活。Cons:如果您只需要一个简单的开关,那么就非常重要。没有多少人这么做,这样的帮助就不会那么容易。
3.欺骗(偏离角度)毕竟是javascript。您可以在window上创建一个类或对象,并调用自封装函数。
template: (function() {
return "<supertemplate-" + window.superTempId + "' />";
}())(免责声明)我还没有测试过这个,但它似乎是可行的
这就是为什么在元数据执行时不存在其他服务的原因,但是如果首先设置模板或其他什么,我就不明白为什么它不能工作了。
Pros:很可能在没有太多麻烦的情况下工作,Cons:非常不是“角的方式”。超级哈奇。
这是一个相当常见的请求,所以我想我们会看到更多关于这方面的“首选方法”或更标准的功能。
希望这能帮上忙!
https://stackoverflow.com/questions/34330484
复制相似问题