从*Routed*Child Component访问Parent @Component和vars

Fir*_*gon 11 angular2-routing angular2-services angular

我正在尝试使用嵌套子组件中的按钮切换位于主App模板顶部的侧面导航菜单.我无法弄清楚如何到达父级中的sidenav组件来告诉它sidenav.open().

我知道子组件上的@Input和@Output,但据我所知,要使用它,我需要为子组件添加某种DOM标记来附加它们吗?如:

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

  <child [someInput]="some_parent_var" (childOpensNav)="sidenav.open()"></child>
</app>
Run Code Online (Sandbox Code Playgroud)

关于如何做到这一点的文章很多.问题是我正在路由到此组件,因此<child>代码中没有明确存在标记.相反,我的代码是这样的:

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

  <router-outlet></router-outlet>
</app>
Run Code Online (Sandbox Code Playgroud)

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

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

// child component
constructor(injector: Injector) {
  this.something = injector.parent.get(Something);
}
Run Code Online (Sandbox Code Playgroud)

或者可能在父级中创建一个服务,以某种方式附加到Sidenav组件,然后将此服务注入到子级中?

rin*_*usu 9

最简单,最干净的方法确实是利用服务.

该服务的外观如下:

export class DomService {
    sidebarVisible: boolean = true;

    showSidebar() {
        sidebarVisible = true;
    }

    hideSidebar() {
        sidebarVisible = false;
    }

    toggleSidebar() {
        sidebarVisible = !sidebarVisible;
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的bootstrap通话中,将服务添加到提供商列表中:

bootstrap(App, [
    // other providers
    DomService
]);
Run Code Online (Sandbox Code Playgroud)

在您想要显示/隐藏侧栏的组件(可能在app.ts您的组件中sidenav.ts)中,添加注入服务:

constructor(private _domService: DomService) {

}
Run Code Online (Sandbox Code Playgroud)

在您希望切换/显示/隐藏的模板中,您现在可以执行以下操作:

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

<div id="toggle-sidebar" (click)="_domService.toggleSidebar()">toggle</div>
Run Code Online (Sandbox Code Playgroud)

  • Intersting,谢谢.我会很快尝试一下.虽然在可以使用`@ViewChild`时必须创建一个访问DOM元素的服务,这似乎违反直觉,似乎Angular 2可以提供类似`@ ViewParent'之类的东西,以使其更直观?会让你知道它对我来说如何.另外,你是如何得到这个答案/了解这是"最佳实践"的?谢谢! (2认同)