You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular9扩展MatDialog报错:私有属性_attachDialogContainer重复声明

Angular 8升级到9后CustomDialog继承MatDialog的问题解决方案

问题根源

Angular 9(及配套的Material 9)中,TypeScript类型检查更严格,同时MatDialog的内部私有方法(如_attachDialogContainer、_createInjector)不再允许子类重写。直接继承并声明同名私有方法会触发类型冲突;去掉@Injectable()则会导致依赖注入系统无法正确初始化父类内部依赖,引发运行时错误。

可行解决方案

方案1:用装饰器模式封装MatDialog(推荐)

放弃继承MatDialog,改为将其作为依赖注入到自定义服务中,通过包装方式扩展功能,完全规避私有方法的访问问题。

示例代码:

@Injectable({ providedIn: 'root' })
export class CustomDialog {
  constructor(private matDialog: MatDialog) {}

  open<T, D = any, R = any>(
    componentType: ComponentType<T>,
    config?: CustomDialogConfig<D>
  ): MatDialogRef<T, R> {
    // 在这里注入自定义逻辑,比如覆盖默认配置、添加全局处理
    const mergedConfig = {
      ...new CustomDialogConfig(),
      ...config,
      containerComponent: CustomDialogContainer // 指定自定义容器组件(如果需要)
    };
    return this.matDialog.open(componentType, mergedConfig as MatDialogConfig<D>);
  }

  // 直接复用MatDialog的原生方法
  closeAll(): void {
    this.matDialog.closeAll();
  }

  getDialogById(id: string): MatDialogRef<any> | undefined {
    return this.matDialog.getDialogById(id);
  }
}

方案2:自定义对话框容器(针对容器逻辑修改需求)

如果核心需求是自定义对话框的容器渲染逻辑,无需继承MatDialog,只需创建MatDialogContainer的子类,在调用open时指定即可。

  1. 创建自定义容器组件:
@Component({
  selector: 'app-custom-dialog-container',
  template: `
    <div class="custom-dialog-wrapper">
      <mat-dialog-title *ngIf="dialogConfig.title">{{ dialogConfig.title }}</mat-dialog-title>
      <mat-dialog-content class="custom-content">
        <ng-template matDialogContent></ng-template>
      </mat-dialog-content>
      <mat-dialog-actions align="end" class="custom-actions">
        <ng-template matDialogActions></ng-template>
      </mat-dialog-actions>
    </div>
  `,
  styles: [`.custom-dialog-wrapper { padding: 16px; }`]
})
export class CustomDialogContainer extends MatDialogContainer {
  constructor(
    overlayRef: OverlayRef,
    @Inject(MAT_DIALOG_DATA) data: any,
    dialogConfig: MatDialogConfig,
    elementRef: ElementRef<HTMLElement>,
    renderer: Renderer2,
    @Optional() @Inject(MAT_DIALOG_SCROLL_STRATEGY) scrollStrategy: ScrollStrategy,
    @Optional() @Inject(MAT_DIALOG_DEFAULT_OPTIONS) defaultOptions: MatDialogConfig
  ) {
    super(overlayRef, data, dialogConfig, elementRef, renderer, scrollStrategy, defaultOptions);
    // 在这里添加容器的自定义逻辑,比如动态修改样式、添加事件监听
  }
}
  1. 在CustomDialog服务中关联容器:
@Injectable({ providedIn: 'root' })
export class CustomDialog {
  constructor(private matDialog: MatDialog) {}

  open<T>(component: ComponentType<T>, config?: CustomDialogConfig) {
    return this.matDialog.open(component, {
      ...config,
      containerComponent: CustomDialogContainer
    });
  }
}

方案3:临时绕过类型检查(不推荐)

如果必须保留原有继承结构,可通过类型断言临时绕过检查,但会破坏类型安全,后续版本升级仍可能出问题:

  • 将子类中_createInjector和_attachDialogContainer的访问修饰符改为/* private */,并添加// @ts-ignore注释
  • 在tsconfig.json中针对当前文件关闭strictPropertyInitialization(不推荐全局关闭)

但强烈建议优先使用前两种方案,避免依赖框架私有API。

内容的提问来源于stack exchange,提问作者Mazhar Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:55:23