将MatDialog弹出窗口添加到Angular Root而不是主体 [英] Add MatDialog popup to Angular Root and not to body

查看:82
本文介绍了将MatDialog弹出窗口添加到Angular Root而不是主体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have made an Angular 6 app where I have some MatDialog. This works perfectly in development mode.

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

Now I have to implement this into an existing website (that uses sitecore 9). This works great, except that the dialogs won't open correctly. I've found out that the dialogs are added to the body and not to my angular root DOM element.

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

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

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

Is there a way to add the dialog to the angular app element (in my case ) and not to the body element?

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

I've already tried to use the viewContainerRef option matDialog, but this doesn't seem to work:

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
    });
  }
}

推荐答案

根据Angular材质 MatDialogConfig 的> docs viewContainerRef 选项是:

According to Angular Material docs, viewContainerRef option of MatDialogConfig is:

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

Where the attached component should live in Angular's logical component tree. This affects what is available for injection and the change detection order for the component instantiated inside of the dialog.

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

When inspecting the DOM when a dialog is opened, we'll find the following component hierarchy:

  1. 正文 -< body>
  2. OverlayContainer -< div class ="cdk-overlay-container"></div>
  3. 重叠 -< div id ="cdk-overlay- {id}" class ="cdk-overlay-pane">
  4. ComponentPortal -< mat-dialog-container></mat-dialog-container>
  5. Component -我们的 ComponentExampleDialog 组件,其打开方式如下: this.dialog.open(ComponentExampleDialog).
  1. Body - <body>
  2. OverlayContainer - <div class="cdk-overlay-container"></div>
  3. Overlay - <div id="cdk-overlay-{id}" class="cdk-overlay-pane">
  4. ComponentPortal - <mat-dialog-container></mat-dialog-container>
  5. Component - our ComponentExampleDialog component, which is opened like: this.dialog.open(ComponentExampleDialog).

现在,我们真正需要更改的是 OverlayContainer 在DOM中的位置,根据

Now, what we really need to change is the position in the DOM of the OverlayContainer, which, according to docs, is:

所有单独的叠加元素都位于其中的容器元素呈现.

the container element in which all individual overlay elements are rendered.

从技术上讲,可以提供自定义覆盖容器,如文档,但不幸的是,它是单个并产生了潜在的问题:

Technically, it is possible to provide a custom overlay container, as described in documentation, but, unfortunately, it is a singleton and creates a potential problem:

MatDialog MatSnackbar MatTooltip MatBottomSheet 以及所有使用 OverlayContainer 的组件code>将在此自定义容器中打开.

MatDialog, MatSnackbar, MatTooltip, MatBottomSheet and all components that use the OverlayContainer will open within this custom container.

如果这不是问题,请使用以下代码,该代码使用 id ="angular-app-root" 将叠加层容器附加到元素:

If this is not a problem, use the following code, which attaches the overlay container to the element with id="angular-app-root":

@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;
    }
  }
}

然后,添加以下CSS:

Then, add the following css:

.app-overlay-container {
  position: absolute;
  z-index: 1000;
  pointer-events: none;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
}

.app-overlay-container:empty {
  display: none;
}

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

Stackblitz demo: https://stackblitz.com/edit/angular-wksbmf

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

Also the following article might be useful, because it contains a similar implementation: https://blog.bbogdanov.net/post/angular-material-overlay-hack-overlay-container/

这篇关于将MatDialog弹出窗口添加到Angular Root而不是主体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆