从任何组件动态更改mat-sidenav内容

时间:2019-06-26 12:07:22

标签: angular angular-material2

我正在尝试通过按钮单击之类的操作从不同的路由组件中加载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中加载不同的组件。

1 个答案:

答案 0 :(得分:4)

使用您的StackBlitz进行实验,我想出了一个使用Angular CDK(组件DevKit)中的portal component的解决方案。

我所做的是修改原始的SidenavService代码,以允许将Portal传递给Subject,这会将Portal传递给所有已订阅Subject。这样,动态sidenav将在sidenav内部有一个<ng-template>部分,其中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>)传递给{ {1}}。这样就可以简化代码,而无需为sidenav的动态内容创建专用组件。

但是,TemplatePortal (which is a Portal that represents an embedded template)要求为第二个参数指定SidenavService。在这种情况下,我要做的是允许用户指定一个ViewContainerRef传递给将用于ViewContainerRef的服务。

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

PanelService

这里有一个StackBlitz供您玩耍。

希望这会有所帮助!