angular - 从任何组件动态更改 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 中的不同组件。
解决方案
通过使用您的 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 TemplatePortal
(Portal
表示嵌入模板的 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供您玩耍。
希望这可以帮助!
推荐阅读
- javascript - 如何克服 NodeJS 堆内存错误?
- google-apps-script - 如何让变量在谷歌表单的 HTML 文件中工作?
- swift - UIBarButtonItem 在作为属性创建时不起作用,但在函数中创建时起作用
- react-native - react-native-maps:动态加载标记:数组不是函数
- python - 在不聚合的情况下计算数据框中的出现次数
- excel - 在数据透视表连接中找不到在电源查询中创建的连接
- javascript - 如何按索引顺序连接 2 个数组?
- android - 无法将 Ionic 4 应用程序部署到 apk
- node.js - Docker MongoNetworkError:通过docker构建Node JS App时连接超时
- flutter - Flutter - 如何在另一个类上显示/隐藏小部件