【问题标题】:Hide element if named router-outlet has active route如果命名路由器出口具有活动路由,则隐藏元素
【发布时间】:2022-08-17 03:15:41
【问题描述】:

我们目前正在开发一个 Angular 13 应用程序,该应用程序分为几个独立的模块,由不同的团队维护,每个模块代表由其自己的微服务支持的不同应用程序的 UI。 这些模块可以依赖于我们的“SharedModule”,但不能反过来。

现在,我们要实现一个“帮助中心”,它由一个浮动在右下角的问号按钮组成,如果单击它会为当前加载的页面提供帮助。问题是,我们希望将每个模块的帮助中心页面的内容保留在该模块中,此外,有些模块不需要帮助中心页面。

我们当前的解决方案在我们的主布局中添加了一个组件:

<router-outlet name=\"navbar\"></router-outlet>

<router-outlet></router-outlet>

<app-help></app-help>

<router-outlet name=\"footer\"></router-outlet>

app-help 组件表示浮动按钮,

<button mat-fab (click)=\"openHelpCenter()\">
  <mat-icon>help</mat-icon>
</button>

打开一个材质对话框,里面有一个名为router-outlet

@Component({
  selector: \'app-help\',
  templateUrl: \'./help.component.html\',
  styleUrls: [\'./help.component.scss\']
})
export class HelpComponent {


  constructor(
    private dialog: MatDialog,
  ) {
  }

  openHelpCenter() {
    this.dialog.open(HelpDialogComponent, {
      width: \'300px\'
    })
  }
}

@Component({
  selector: \'app-help-dialog\',
  template: \'<router-outlet name=\"help\"></router-outlet>\'
})
export class HelpDialogComponent {

  constructor() {
  }
}

在每个模块中,团队现在可以实现使用命名router-outlet 的路由:

...
{
        path: \'\',
        component: HelpComponent,
        outlet: \'help\'
}
...

根据当前加载的 url “注入” Dialog 内的模块 HelpComponent。

这工作得很好,但是,我们有一个悬而未决的问题:

如果路由器插座为空,即如果您位于不提供帮助的页面上,我们如何隐藏浮动按钮?

我相信最简单的解决方案(即在模块内用最少的代码管理东西的解决方案)是在HelpComponent 中监听路由器事件,例如NavigationEnd,然后找出“帮助”-router-outlet 是否存在“活动”路由并相应地设置可见性。 (类似于RouterLinkActive-指令)

但是,我无法找到如何从Router-Framework 检索此信息。

当然,我也很欣赏有关如何以不同方式解决问题的想法。

    标签: angular angular-router angular-router-events


    【解决方案1】:

    您可以让服务持有一个布尔值,并让模块在初始化时手动打开或关闭帮助以满足他们的需求。我们在我们的应用程序中做了类似的事情,但也订阅了基于某些路线翻转的导航事件。

    您还可以将查询参数添加到类似于 showhelp=true 或 false 的路由中,并在主组件中对此做出反应。

    您还可以在主组件中有一个白名单,您可以在其中按住帮助按钮并在此处收听路由事件,然后只需使用映射来控制其上的 ngif。

    很多选择,不知道什么是最好的,我很好奇你最终会采取什么路线

    【讨论】:

    • 感谢您的建议,我认为您的建议是合理的,肯定会奏效。问题是,它们都需要模块做额外的工作,我真的尽量保持在最低限度:服务解决方案和查询参数将要求所有模块组件打开和关闭开关,这会增加复杂性模块。白名单选项恕我直言违反了允许的依赖方向。
    • 是的,理想情况下,我们可以只检查一条路线的存在,但如果可以的话,那就别想了。我想知道你是否可以在 helpDialogComponent 中使用一个 viewchild 来抓取路由器所拥有的任何东西,如果它没有看到任何东西就不会显示任何东西。我从来没有做过这样的事情,但听起来很酷,如果你尝试一下,让我知道你发现了什么
    • 我想我找到了解决办法。请检查我的回答
    【解决方案2】:

    在阅读了 Angular Router 的源代码后,我偶然发现了ChildrenOutletContexts,它似乎是当前“活动”网点的地图。

    我调整了我的组件以使其注入并在每次导航完成时检查它:

    import {
      ChildrenOutletContexts,
      NavigationEnd,
      Router
    } from "@angular/router";
    import {filter} from "rxjs";
    import {map} from "rxjs/operators";
    
    @Component({
      selector: 'app-help',
      templateUrl: './help.component.html',
      styleUrls: ['./help.component.scss']
    })
    export class HelpComponent {
      helpOutletActive$ = this.router.events.pipe(
        filter(event => event instanceof NavigationEnd),
        map(() => this.contexts.getContext('help') !== null)
      )
    
      constructor(
        private dialog: MatDialog,
        private router: Router,
        private contexts: ChildrenOutletContexts
      ) {
      }
    
      openHelpCenter() {
        this.dialog.open(HelpDialogComponent, {
          width: '300px'
        })
      }
    }
    

    根据我的测试,这似乎产生了预期的结果

    【讨论】:

      【解决方案3】:

      使用 RouterLinkActive 指令还有另一种解决方案

      <div routerLink="/specific/route" routerLinkActive="d-none">
         ... show/hide content on a specific route ... 
      </div>
      

      样式.scss

      .d-none {
        display: none
      }
      

      【讨论】:

        猜你喜欢
        • 2018-07-27
        • 2017-12-03
        • 2018-04-15
        • 2018-02-10
        • 2017-12-07
        • 2019-05-17
        • 2017-07-19
        • 2019-12-07
        • 2018-09-12
        相关资源
        最近更新 更多