首页 > 解决方案 > 从任何组件动态更改 mat-sidenav 内容

问题描述

我正在尝试根据某些操作(例如按钮单击)从不同的路由组件中加载 mat-sidenav 中的不同组件?

我创建了一个单例服务“SidenavService”来使用@ViewChild 获取对mat-sidenav 的引用,这样我就可以从应用程序中的任何位置控制(如打开、关闭、切换等)sidenav。

我还在 mat-sidenav 中创建了一个 ng-container 并将其 ViewConteinerRef 存储在 SidenavService 中,现在在组件层次结构中的任何组件中,我可以注入 SidenavService 并且可以使用 ViewConteinerRef 来创建嵌入式视图。

stackblitz 链接 https://stackblitz.com/edit/angular-material-sidenav-dynamic-content

有没有更好的方法来实现这一目标?从应用程序的任何位置加载 mat-sidenav 中的不同组件。

标签: angularangular-material2

解决方案


通过使用您的 StackBlitz 进行试验,我提出了一个使用Angular CDK(组件 DevKit)中的门户组件的解决方案。

我所做的是修改原始SidenavService代码以允许将 aPortal传递给 a Subject,该 a 将向Portal已订阅Subject. 然后,动态 sidenav 将<ng-template>在 sidenav 内部有一部分,其cdkPortalOutlet属性绑定到Portal Subject

<mat-sidenav #rightPanel position="end">
  <ng-template [cdkPortalOutlet]="panelService.panelPortal | async"></ng-template>
</mat-sidenav>
export class AppComponent {
  constructor(public panelService: PanelService) { }
}

但是,请务必PortalModule@angular/cdk/portal入口点导入应用程序的模块:

import { PortalModule } from '@angular/cdk/portal';
// ...

@NgModule({
  imports: [
    // ...
    PortalModule
  ],
  // ...
})

通过允许SidenavService代码允许Portal引用,您现在可以将模板引用 ( TemplateRef<T>) 或组件 ( ComponentType<T>) 传递给SidenavService. 这可以简化代码,无需为 sidenav 的动态内容创建专用组件。

但是,a TemplatePortalPortal表示嵌入模板的 a)要求ViewContainerRef为第二个参数指定 a。在这种情况下,我所做的是允许用户指定ViewContainerRef要传递给将用于TemplatePortal.

无论如何,这是服务代码的一部分。(注:我已将服务名称修改为更好听的名称PanelService:)

import { from } from 'rxjs';
// ...

export class PanelService {
  /** The panel. */
  panel: MatSidenav;
  private vcr: ViewContainerRef;
  // Note: The Portal class requires that a generic is specified for the component/template type.
  private panelPortal$ = new Subject<Portal<any>>();

  get panelPortal() {
    return from(this.panelPortal$); // Or this.panelPortal$.asObservable()
  }

  setViewContainerRef(vcr: ViewContainerRef) {
    this.vcr = vcr;
  }

  setPanelPortal(portal: Portal<any>) {
    this.panelPortal$.next(portal);
  }

  // Wrapper methods for MatSidenav go here.
  // ...
}

这是一个StackBlitz供您玩耍。

希望这可以帮助!


推荐阅读