首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角度2:从装饰器访问注入依赖项

角度2:从装饰器访问注入依赖项
EN

Stack Overflow用户
提问于 2015-12-17 09:03:49
回答 2查看 818关注 0票数 5

我正在制作一个可重用的Angular2组件,我希望用户能够指定一个模板字符串或templateUrl,然后该组件将通过属性或通过某种服务方法设置它。

在角1中,这很简单,我们可以这样做:

代码语言:javascript
复制
// 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中实现的?

代码语言:javascript
复制
@Component({
  selector: 'my-component',
  template: '...' // cannot see `mySerivce` from here, nor access the element attributes
})
export class MyComponent {

  constructor(private myService: MyService) {}

}

虽然我的问题具体涉及如何实现动态模板,但更广泛的问题是是否可以从各个装饰器访问注入的依赖实例。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-26 09:43:14

所以我终于想出了一种用定制模板来做我想做的事情的方法。

我认为实际问题的答案必须是否,在装饰器中不能使用注入器。这是我对角质2的生命周期的理解。

对于那些感兴趣的人,下面是我为实现用户定义的自定义模板而提出的:

给定一个指令SimpleTimer,我们可以提供如下自定义模板:

代码语言:javascript
复制
<!-- 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注入器,如下所示:

代码语言:javascript
复制
// 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());
}

想了解一下这是如何工作的,为什么要这样做,请看我写的关于这个话题的博客文章。

票数 3
EN

Stack Overflow用户

发布于 2015-12-17 23:27:51

编辑:我刚刚注意到您的目的是访问DI。现在你不能,因为他们开得太晚了。这个答案的其余部分是做你问过的模板内容。

我对这个问题很感兴趣,所以我花了比我想象的更多的时间来研究这个问题。据我所知,目前还没有一种轻松的方法可以做到这一点。

你有三个主要选择:

1.使用*ng-如果使用已知组件

这是迄今为止解决这一问题的最简单方法。通过只有几个选项,您只能加载所需的组件。

代码语言:javascript
复制
<special *ngIf="!type">Default</special>
<special *ngIf="type == 'awesome'"> I'm Awesome </special>
<special *ngIf="type == 'admin'">Admin Only</special>

Pros:轻松,模板语法。Cons:必须知道类型,当有许多选项时会变得很烦人

2.使用DynamicComponentLoader动态创建组件

这是毛茸茸的,而且相当先进。基本上,您可以根据传递的参数调用加载组件。这将允许您定义模板值,然后传递它以创建新组件。

这是一篇学习如何开始使用它的好文章。

这是一个S.O.答案,它使用了这个精确的方法

下面是使用它来动态加载组件的人(超级黑客,捣乱asyncRouter)

Pros:解决这个问题的“角度”方式,超级灵活。Cons:如果您只需要一个简单的开关,那么就非常重要。没有多少人这么做,这样的帮助就不会那么容易。

3.欺骗(偏离角度)毕竟是javascript。您可以在window上创建一个类或对象,并调用自封装函数。

代码语言:javascript
复制
template: (function() {
    return "<supertemplate-" + window.superTempId + "' />";
}())

(免责声明)我还没有测试过这个,但它似乎是可行的

这就是为什么在元数据执行时不存在其他服务的原因,但是如果首先设置模板或其他什么,我就不明白为什么它不能工作了。

Pros:很可能在没有太多麻烦的情况下工作,Cons:非常不是“角的方式”。超级哈奇。

这是一个相当常见的请求,所以我想我们会看到更多关于这方面的“首选方法”或更标准的功能。

希望这能帮上忙!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34330484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档