将MatDialog弹出窗口添加到Angular Root而不是主体

时间:2018-10-11 15:00:34

标签: angular angular-material2

我制作了一个Angular 6应用,其中有一些MatDialog。在开发模式下可以完美运行。

现在,我必须将其实现到现有网站(使用sitecore 9)中。 这很好用,只是对话框无法正确打开。 我发现对话框被添加到主体中,而不是我的有角根DOM元素中。

<html>
  <head></head>
  <body>
    <app-library>...</app-library>

    <div class="cdk-overlay-container">...</div>
  </body>
</html>

是否可以将对话框添加到有角度的app元素(在我的情况下)而不是body元素?

我已经尝试使用viewContainerRef选项matDialog,但这似乎不起作用:

export class AppComponent implements OnInit {
  constructor(..., public viewRef: ViewContainerRef) {
}

export class FilterToggleComponent implements OnInit {
  constructor(..., public dialog: MatDialog, private appRef: ApplicationRef) {}
  openFilterPanel() {
    const viewRef = (this.appRef.components[0].instance as AppComponent).viewRef;
    const dialogRef = this.dialog.open(FilterPanelComponent, {
      width: '100vw',
      height: '100%',
      panelClass: 'search-filter-panel-modal',
      viewContainerRef: viewRef
    });
  }
}

1 个答案:

答案 0 :(得分:0)

根据角材料docsviewContainerRef的{​​{1}}选项为:

附加组件应位于Angular逻辑组件树中的位置。这会影响可用于注入的内容以及在对话框内部实例化的组件的更改检测顺序。

这不会影响对话框内容的呈现位置。

在打开对话框时检查DOM时,我们将找到以下组件层次结构:

  1. MatDialogConfig -Body
  2. <body> -OverlayContainer
  3. <div class="cdk-overlay-container"></div> -Overlay
  4. <div id="cdk-overlay-{id}" class="cdk-overlay-pane"> -ComponentPortal
  5. <mat-dialog-container></mat-dialog-container> -我们的Component组件,其打开方式为:ComponentExampleDialog

现在,我们真正需要更改的是this.dialog.open(ComponentExampleDialog)在DOM中的位置,根据docs,这是:

所有单个叠加层元素都位于其中的容器元素 呈现。

默认情况下,覆盖容器直接附加到文档主体。

从技术上讲,可以提供{strong>自定义的叠加层容器,如documentation中所述,但是很遗憾,它是 singleton ,并有潜力问题:

OverlayContainerMatDialogMatSnackbarMatTooltip和所有使用MatBottomSheet的组件将在此自定义容器中打开。

如果这不是问题,请使用以下代码,该代码使用OverlayContainer将覆盖容器附加到元素:

id="angular-app-root"

然后,添加以下CSS:

@NgModule({
  providers: [{provide: OverlayContainer, useClass: AppOverlayContainer}],
 // ...
})
export class MyModule { }

export class AppOverlayContainer extends OverlayContainer {

  protected _createContainer(): void {
    const container: HTMLDivElement = document.createElement('div');
    container.classList.add('app-overlay-container');

    const element: Element | null = document.querySelector('#angular-app-root');
    if (element !== null) {
      element.appendChild(container);
      this._containerElement = container;
    }
  }
}

Stackblitz演示:https://stackblitz.com/edit/angular-wksbmf

此外,以下文章可能会有用,因为它包含类似的实现: https://blog.bbogdanov.net/post/angular-material-overlay-hack-overlay-container/