我正在尝试通过按钮单击之类的操作从不同的路由组件中加载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中加载不同的组件。
答案 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供您玩耍。
希望这会有所帮助!