如何在打开Angular Material弹窗时向动态加载的子组件传参
实现步骤
第一步:定义通用注入令牌
专门用于传递动态组件的入参,新建popup-tokens.ts文件:
import { InjectionToken } from '@angular/core'; // 定义注入令牌,用于传递子组件参数 export const POPUP_CHILD_DATA = new InjectionToken<any>('POPUP_CHILD_DATA');
第二步:改造PopupShell组件,生成自定义注入器
修改popup-shell.component.ts
引入依赖并生成适配的注入器,把需要传给子组件的参数和MatDialog实例都注入到动态组件的上下文里:
import { Component, Inject, Injector } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { POPUP_CHILD_DATA } from './popup-tokens'; @Component({ // 原有组件配置保持不变 selector: 'app-popup-shell', templateUrl: './popup-shell.component.html' }) export class PopupShellComponent { constructor( public dialogRef: MatDialogRef<PopupShellComponent>, @Inject(MAT_DIALOG_DATA) public data: any, // 注入当前Injector作为父注入器 private injector: Injector ) {} // 生成动态组件专用的注入器 get componentInjector(): Injector { return Injector.create({ parent: this.injector, providers: [ // 传递子组件需要的自定义数据 { provide: POPUP_CHILD_DATA, useValue: this.data.componentData }, // 传递弹窗实例,方便子组件控制弹窗关闭、返回结果 { provide: MAT_DIALOG_DATA, useValue: this.data } ] }); } }
修改popup-shell.component.html
给ngComponentOutlet绑定自定义注入器:
<mat-dialog-content class="mat-typography popup-shell"> <div class="popup-shell__container"> <ng-container *ngComponentOutlet="data.component; injector: componentInjector"></ng-container> </div> </mat-dialog-content>
第三步:打开弹窗时传入子组件参数
调用open方法时在data里新增componentData字段,传入所有要给子组件的参数:
import { MatDialog } from '@angular/material/dialog'; import { PopupShellComponent } from './popup-shell.component'; import { UserPopupComponent } from './user-popup/user-popup.component'; // 你的业务组件代码 constructor(private dialog: MatDialog) {} openPopup() { const dialogRef = this.dialog.open(PopupShellComponent, { data: { component: UserPopupComponent, // 这里放所有要传给UserPopupComponent的参数 componentData: { userId: 1001, userName: '测试用户', editMode: true } }, }); // 可订阅弹窗关闭事件拿子组件返回的结果 dialogRef.afterClosed().subscribe(result => { console.log('弹窗返回结果', result); }) }
第四步:子组件中直接注入获取参数
在UserPopupComponent中注入POPUP_CHILD_DATA即可拿到传递的参数,注入MatDialogRef即可控制弹窗:
import { Component, Inject } from '@angular/core'; import { MatDialogRef } from '@angular/material/dialog'; import { POPUP_CHILD_DATA } from '../popup-tokens'; @Component({ // 原有组件配置不变 selector: 'app-user-popup', templateUrl: './user-popup.component.html' }) export class UserPopupComponent { constructor( // 注入拿到父级传递的参数 @Inject(POPUP_CHILD_DATA) public popupData: any, // 注入弹窗实例控制弹窗 private dialogRef: MatDialogRef<PopupShellComponent> ) {} ngOnInit() { // 直接使用参数即可 console.log('拿到的用户ID', this.popupData.userId); console.log('拿到的用户名', this.popupData.userName); } // 子组件主动关闭弹窗并返回结果 close() { this.dialogRef.close({ success: true, data: '子组件返回的结果' }) } }
注意事项
- 如果你用的是Angular 14+的standalone组件,确保POPUP_CHILD_DATA和MatDialog相关依赖在子组件的imports或者providers里正确声明
- Angular 9+之后使用ivy编译器,动态加载的组件不需要额外加到entryComponents里
内容的提问来源于stack exchange,提问作者Oleg Shchegolev
相关产品推荐
相关产品推荐

