2016-06-11 49 views
10

我想切换侧边导航菜单,位于我的主要应用程序模板的顶部使用嵌套子组件中的按钮。我无法弄清楚如何到父母的sidenav组件,告诉它sidenav.open()访问父@分量和变量*路由*子组件

我知道@Input和@Output在一个子组件上,但据我了解,使用这个我需要有一些DOM标签给子组件来附加这些?如:

<app> 
    <sidenav-component #sidenav>...</sidenav-component> 

    <child [someInput]="some_parent_var" (childOpensNav)="sidenav.open()"></child> 
</app> 

吨如何做到这一点的文章。问题是我路由到这个组件,所以没有<child>标签显式存在于代码中。而是我的代码是这样的:

<app> 
    <sidenav-component #sidenav>...</sidenav-component> 

    <router-outlet></router-outlet> 
</app> 

如果我有被路由到一个子组件,我该怎么做sidenav.open()或以某种方式从孩子在家长访问组件?

一些想法:我已经做了一些研究并考虑了一些方法,并且不确定它们是否正确或者甚至可以工作......一种方法是使用Injector服务并尝试遍历父级,但这种感觉不对:

// child component 
constructor(injector: Injector) { 
    this.something = injector.parent.get(Something); 
} 

或可能创建父服务,以某种方式连接到Sidenav组件,然后注射这种服务到孩子?

+0

这实际上就是我试图做的事情。我不相信我发现你的问题。谢谢。希望我会向下滚动并得到一个很好的答案。 – krummens

回答

9

最简单和最干净的方式确实是利用服务。

怎么可能看起来像服务:

export class DomService { 
    sidebarVisible: boolean = true; 

    showSidebar() { 
     sidebarVisible = true; 
    } 

    hideSidebar() { 
     sidebarVisible = false; 
    } 

    toggleSidebar() { 
     sidebarVisible = !sidebarVisible; 
    } 
} 

在你bootstrap通话服务添加到供应商的名单:

bootstrap(App, [ 
    // other providers 
    DomService 
]); 

在组件(也许在app.ts,而且在你的sidenav.ts)你想要显示/隐藏侧边栏添加注射服务:

constructor(private _domService: DomService) { 

} 

在模板中,要切换/显示/隐藏,你现在可以做的:

<sidenav-component *ngIf="_domService.sidebarVisible">...</sidenav-component> 

<div id="toggle-sidebar" (click)="_domService.toggleSidebar()">toggle</div> 
+2

Intersting,谢谢。我会尽快尝试。虽然在'@ ViewChild'可用时必须创建一个访问DOM元素的服务,但它似乎违反直觉,似乎Angular 2可以提供类似'@ ViewParent'的东西或其他东西以使其更直观?请让你知道它对我而言如何。另外,你是如何得到这个答案/知道这是“最佳实践”的?谢谢! – FireDragon

+0

那么,基本上你可以在你的[输入和输出属性](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#input-and-output-properties)上做到这一点'sidenav-component'标签,但如果你需要从其他几个地方使用它,这将变得非常混乱。 – rinukkusu

0

我喜欢接受的答案,似乎是一种更稳健的角度的方式做正确(尤其是如果你打算要添加更多选项)。

但是,我想通过Id快速脏访问全局元素。每个人都在谈论使用@ViewChild,但我想走上树。我刚回到学校,并在组件方法中使用这样的:

document.getElementById('nav-panel').className = 'hide'; 

如果我们想这多份工作(例如,左,右侧菜单),我们需要注入下来的东西孩子们,让他们知道哪些编号寻找。