【问题标题】:Inject higher parent component (not direct parent) to child in angular 2将更高的父组件(不是直接父组件)注入角度 2 的子组件
【发布时间】:2017-05-18 04:02:40
【问题描述】:

我需要注入一个不是直接父级的父级组件。

@Host() 装饰器只允许注入直接父组件。

真实示例 - 菜单和菜单项组件。我想在页面上放置菜单

<menu [name]="'smth'">
  <auth-logout></auth-logout>
  <!-- ... other menu items -->
</menu>

name 输入通过菜单服务调用菜单上的操作(例如切换)。 任何菜单项子组件都可以包含menu-item组件

<menu-item (itemClick)="logout()">
  LOGOUT
</menu-item>

menu-item模板

<div class="menu-item"    
     (click)="onClick()">
  <ng-content></ng-content>
</div>

plnkrhttp://plnkr.co/edit/ArQZYZsHQgn6I2eK3AZd

我想将menu 组件注入menu-item 以在menu-item 点击事件上调用close() 方法。 auth-logout 不应该对这个菜单组件交互一无所知,我不想在每个菜单项中重复关闭逻辑。

为什么不这样包装?

<menu>
  <menu-item>
    <auth-logout></auth-logout>
  </menu-item>
</menu>

因为menu-item 块有一些样式会破坏正确单击子组件(例如填充),并且很难在单击时自动关闭菜单(需要将菜单名称传递给每个组件,例如 auth-logout 或在此组件中添加输出)

为什么不使用来自menu-item 的服务调用? 因为它需要将菜单名称传递给每个菜单项(如auth-logout)并向下传递到menu-item,但像auth-logout 这样的组件不应该知道有关此交互或菜单名称或其他任何内容的任何信息。

另一个例子 - 带有一些项目子组件的项目列表,它监听列表更改事件(列表组件中的主题)并在发出时做一些事情(例如项目图像 src 通过添加新的时间戳参数来更新缓存以重置缓存并更新图像)。由于组件嵌套较深,通过服务交互传递列表名称过于复杂(由于页面上的列表不同,需要名称)

这种情况在带有require 属性的ng1 中运行良好,允许向组件注入任何更高级别的父级

更新:

可以通过删除@Host() 并在构造函数注入中添加错过的private 来修复上面的示例(谢谢@yurzui)。 但真正的问题更复杂,这个解决方案没有帮助。这是更新的plnkr。 http://plnkr.co/edit/p7Vd4FRpHPRtyEuL6pEZ

不同之处是添加了header-menu有这个模板的组件

<menu>
  <ng-content></ng-content>
</menu>

并且将menu 注入menu-item 组件不适用于此组件嵌套

header-menu
  menu
    auth-logout
      menu-item

更新/回答: header-menu 的最终案例属于此问题 github.com/angular/angular/issues/5126,目前尚不支持。

【问题讨论】:

    标签: angularjs angular


    【解决方案1】:

    这是修改后的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,然后您可以在菜单项中调用menu.close()

    【讨论】:

      【解决方案2】:

      只需删除 @Host() 装饰器,不要忘记 private。否则 this.menuComponent 将永远是 undefined 没有 private 修改。

      constructor (@Optional() private menuComponent: MenuComponent)
      

      Plunker Example

      【讨论】:

      • 嗯,很奇怪我错过了private。是的,它适用于我的示例,但这在实际应用程序中不起作用,我进行了更多调试并为问题添加了更新。
      • 在 Angular gitter 中得到答案:这种情况现在不支持 - github.com/angular/angular/issues/5126
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 2017-07-09
      • 2020-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多