我需要注入一个不是直接父级的父组件。
@Host()
装饰器允许只注入直接父组件。
真实示例 - 菜单和菜单项组件。我想在页面上放置菜单
<menu [name]="'smth'">
<auth-logout></auth-logout>
<!-- ... other menu items -->
</menu>
name
通过菜单服务在菜单(e.x. toggle)上输入操作。
任何菜单项子组件都可以包含menu-item
组件
<menu-item (itemClick)="logout()">
LOGOUT
</menu-item>
和menu-item
模板
<div class="menu-item"
(click)="onClick()">
<ng-content></ng-content>
</div>
plnkr http://plnkr.co/edit/ArQZYZsHQgn6I2eK3AZd
我想将menu
组件注入menu-item
,以便在close()
点击事件上调用menu-item
方法。 auth-logout
不应该对这个菜单组件交互有任何了解,我也不想在每个菜单项中复制关闭逻辑。
为什么不这样包裹?
<menu>
<menu-item>
<auth-logout></auth-logout>
</menu-item>
</menu>
因为menu-item
块有一些样式会破坏正确点击子组件(ex padding),并且很难在点击时自动关闭菜单(需要将菜单名称传递给每个组件,如{{1或者在这个组件中添加输出)
为什么不使用来自auth-logout
的服务电话?
因为它需要将菜单名称传递到每个菜单项(例如menu-item
)并向下传递到auth-logout
,但像menu-item
这样的组件不应该知道有关此交互或菜单名称或其他任何内容的任何内容
还有一个例子 - 带有一些项目子组件的项目列表,它监听列表更改事件(列表组件中的主题)并通过添加新的时间戳参数来发出一些内容(ex item image auth-logout
更新重置缓存和更新图像)。由于深层组件嵌套(由于页面上的不同列表需要名称),传递列表名称以通过服务进行交互太复杂了
这种情况在ng1中运行良好,src
属性允许将任何更高级别的父级注入组件
更新
上面的示例可以通过删除require
并在构造函数注入中添加遗漏@Host()
来解决(thx @yurzui)。
但真正的问题更复杂,这个解决方案没有帮助。这是更新的plnkr。
http://plnkr.co/edit/p7Vd4FRpHPRtyEuL6pEZ
差异是添加了具有此模板的private
组件
header-menu
将<menu>
<ng-content></ng-content>
</menu>
注入menu
组件不适用于此组件嵌套
menu-item
更新/答案:
header-menu
menu
auth-logout
menu-item
的最终案例属于这个问题github.com/angular/angular/issues/5126,这还不支持。
答案 0 :(得分:3)
只需删除@Host()
装饰,不要忘记private
。否则,this.menuComponent
将始终为undefined
而不进行private
修改。
constructor (@Optional() private menuComponent: MenuComponent)
<强> Plunker Example 强>
答案 1 :(得分:0)
此处修改了plunkr
这是传递实例的一种方法:使用Template reference variables。
注射对我来说太复杂了。
在app.component.html中:
<menu #mm><!-- use whatever name after # -->
<auth-logout [menu]='mm'></auth-logout>
</menu>
在auth-logout.component.html中:
<menu-item (itemClick)="logout()" [menu]="menu">
LOGOUT
</menu-item>
在auth-logout.component.ts中:
@Input() menu: MenuComponent;
在menu-item.component.ts中:
@Input() menu: MenuComponent;
#mm
(MenuComponent的实例)将作为menu
向下传递到auth-logout,然后向下传递到菜单项menu
,然后您可以调用{{菜单项中的1}}。