从 *Routed* 子组件访问父 @Component 和变量

Access Parent @Component and vars from *Routed* Child Component

我正在尝试使用嵌套子组件中的按钮切换位于我的主应用程序模板顶部的侧边导航菜单。我不知道如何到达父级中的 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 组件,然后将此服务注入子级??

最简单、最干净的方法确实是利用服务。

服务可能的样子:

export class DomService {
    sidebarVisible: boolean = true;

    showSidebar() {
        sidebarVisible = true;
    }

    hideSidebar() {
        sidebarVisible = false;
    }

    toggleSidebar() {
        sidebarVisible = !sidebarVisible;
    }
}

在您的 bootstrap 调用中将服务添加到提供商列表中:

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

在您想要 show/hide 侧边栏添加注入服务的组件中(可能在 app.ts 但也可能在您的 sidenav.ts 中):

constructor(private _domService: DomService) {

}

在你的模板中,你想切换的地方/show/hide你现在可以做的:

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

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

我喜欢接受的答案,似乎是一种更可靠的 Angular 方式来正确地做到这一点(特别是如果您要添加更多选项)。

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

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

如果我们想让它的多个副本起作用(例如左侧和右侧菜单),我们需要在 children 下注入一些东西,这样他们就知道要查找哪个 ID。