【问题标题】:Access Parent @Component and vars from *Routed* Child Component从 *Routed* 子组件访问父 @Component 和 vars
【发布时间】:2016-10-12 15:47:42
【问题描述】:

我正在尝试使用嵌套子组件中的按钮切换位于主应用模板顶部的侧导航菜单。我不知道如何到达父级中的 sidenav 组件以将其告诉sidenav.open()

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

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

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

关于如何做到这一点的大量文章。问题是我正在路由到这个组件,所以代码中没有明确存在&lt;child&gt; 标记。而我的代码是这样的:

<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 组件,然后将该服务注入子级??

【问题讨论】:

  • 这正是我想要做的。我不敢相信我找到了你的问题。谢谢。希望我会向下滚动并得到一个好的答案。

标签: angular angular2-routing angular2-services


【解决方案1】:

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

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

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

如果我们想要这个的多个副本工作(例如左侧和右侧菜单),我们需要在孩子们身上注入一些东西,这样他们就知道要寻找哪个 Id。

【讨论】:

    【解决方案2】:

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

    服务的样子:

    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>
    

    【讨论】:

    • 很有趣,谢谢。我很快就会试试这个。虽然当有@ViewChild 可用时必须创建一个访问DOM 元素的服务是违反直觉的,但Angular 2 似乎可以提供@ViewParent 之类的东西或者让它更直观的东西?会让你知道它对我的影响。另外,您是如何得到这个答案/知道这是“最佳实践”的?谢谢!
    • 嗯,基本上你可以在你的sidenav-component 标签上使用input and output properties 来做到这一点,但是如果你需要从其他几个地方使用它,这将变得非常混乱。
    猜你喜欢
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    相关资源
    最近更新 更多