0

我们目前正在开发一个 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-Directive)

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

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

4

2 回答 2

1

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

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

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

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

于 2022-02-02T16:36:00.410 回答
1

在阅读了 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'
    })
  }
}

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

于 2022-02-02T20:47:09.897 回答