我正在尝试在mat-sidenav中加载不同的组件,这些组件来自不同的路由组件,基于某些操作,比如单击按钮?
我已经创建了一个单独的服务'SidenavService‘来使用@ViewChild获取对mat-sidenav的引用,这样我就可以控制(如打开、关闭、切换等)。应用程序中的任何位置都可以使用sidenav。
我还在mat-sidenav中创建了一个ng容器,并将其ViewConteinerRef存储在SidenavService中,现在在组件层次结构中的任何组件中,我可以注入SidenavService,我可以使用ViewConteinerRef创建嵌入式视图。
stackblitz链接https://stackblitz.com/edit/angular-material-sidenav-dynamic-content
有没有更好的方法来实现这一点?从应用程序的任何位置加载mat-sidenav中的不同组件。
发布于 2020-01-02 22:04:54
在试验您的StackBlitz时,我想出了一个使用Angular CDK (组件DevKit)中的portal component的解决方案。
我所做的是修改原始的SidenavService代码,以允许将Portal传递给Subject,该any将向订阅了该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)或组件(ComponentType)传递给SidenavService。这允许简化代码,其中不需要为sidenav的动态内容创建专用组件。
但是,TemplatePortal (which is a Portal that represents an embedded template)要求为第二个参数指定ViewContainerRef。在这种情况下,我所做的是允许用户指定要传递给将用于TemplatePortal的服务的ViewContainerRef。
无论如何,这是服务代码的一部分。(注意:我已经将服务名称修改为一个听起来更好的名称: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供您试用。
希望这能有所帮助!
https://stackoverflow.com/questions/56772447
复制相似问题