将 MatDialog 弹出窗口添加到 Angular Root 而不是主体 [英] Add MatDialog popup to Angular Root and not to body
问题描述
我制作了一个 Angular 6 应用程序,其中有一些 MatDialog.这在开发模式下非常有效.
现在我必须将其实施到现有网站(使用 sitecore 9)中.这很好用,只是对话框无法正确打开.我发现对话框被添加到主体而不是我的角度根 DOM 元素.
<头></头><身体><app-library>...</app-library><div class="cdk-overlay-container">...</div></html>
有没有办法将对话框添加到 angular app 元素(在我的例子中)而不是 body 元素?
我已经尝试使用 viewContainerRef 选项 matDialog,但这似乎不起作用:
导出类 AppComponent 实现 OnInit {构造函数(...,公共视图引用:ViewContainerRef){}导出类 FilterToggleComponent 实现 OnInit {构造函数(..., 公共对话框: MatDialog, 私有 appRef: ApplicationRef) {}打开过滤器面板(){const viewRef = (this.appRef.components[0].instance as AppComponent).viewRef;const dialogRef = this.dialog.open(FilterPanelComponent, {宽度:'100vw',高度:'100%',面板类:'搜索过滤器面板-模态',视图容器引用:视图引用});}}
根据 Angular Material docs, viewContainerRef
MatDialogConfig
的选项是:
附加组件应该在 Angular 的逻辑组件树中的位置.这会影响可用于注入的内容以及在对话框内实例化的组件的更改检测顺序.
这不会影响对话框内容的呈现位置.
在打开对话框时检查 DOM 时,我们会发现以下组件层次结构:
Body
-OverlayContainer
-</div>叠加
-ComponentPortal
-Component
- 我们的ComponentExampleDialog
组件,其打开方式如下:this.dialog.open(ComponentExampleDialog)
.现在,我们真正需要改变的是
<块引用>OverlayContainer
在 DOM 中的位置,根据 文档,是:所有单独的叠加元素所在的容器元素呈现.
默认情况下,覆盖容器直接附加到文档正文.
从技术上讲,可以提供自定义覆盖容器,如文档,但不幸的是,它是一个单例,并且会产生一个潜在的问题:
MatDialog
、MatSnackbar
、MatTooltip
、MatBottomSheet
和所有使用OverlayContainer的组件code> 将在此自定义容器中打开.
如果这不是问题,请使用以下代码,它将覆盖容器附加到具有
id="angular-app-root"
的元素:@NgModule({提供者:[{provide: OverlayContainer, useClass: AppOverlayContainer}],//...})导出类 MyModule { }导出类 AppOverlayContainer 扩展 OverlayContainer {受保护的_createContainer():无效{const 容器:HTMLDivElement = document.createElement('div');container.classList.add('app-overlay-container');const 元素: 元素 |null = document.querySelector('#angular-app-root');如果(元素!== 空){element.appendChild(容器);this._containerElement = 容器;}}}
然后,添加以下css:
.app-overlay-container {位置:绝对;z-索引:1000;指针事件:无;顶部:0;左:0;高度:100%;宽度:100%;}.app-overlay-container:empty {显示:无;}
Stackblitz 演示:https://stackblitz.com/edit/angular-wksbmf
以下文章也可能有用,因为它包含类似的实现:https://blog.bbogdanov.net/post/angular-material-overlay-hack-overlay-container/
I have made an Angular 6 app where I have some MatDialog. This works perfectly in development mode.
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>
Is there a way to add the dialog to the angular app element (in my case ) and not to the body element?
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 }); } }
解决方案According to Angular Material docs,
viewContainerRef
option ofMatDialogConfig
is: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.
This does not affect where the dialog content will be rendered.
When inspecting the DOM when a dialog is opened, we'll find the following component hierarchy:
Body
-<body>
OverlayContainer
-<div class="cdk-overlay-container"></div>
Overlay
-<div id="cdk-overlay-{id}" class="cdk-overlay-pane">
ComponentPortal
-<mat-dialog-container></mat-dialog-container>
Component
- ourComponentExampleDialog
component, which is opened like:this.dialog.open(ComponentExampleDialog)
.
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.
By default, the overlay container is appended directly to the document body.
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
and all components that use theOverlayContainer
will open within this custom container.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; } } }
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 demo: https://stackblitz.com/edit/angular-wksbmf
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屋!
查看全文
相关文章
- 将MatDialog弹出窗口添加到Angular Root而不是主体;
- 将 JPG 图像添加到叶弹出窗口;
- 将孩子添加到弹出窗口中.(JavaScript);
- 如何将主体添加到 Angular HttpClient 删除功能;
- 如何将主体添加到Angular HttpClient删除功能;
- AFHTTPSessionManager将主体添加到POST;
- 使用弹出窗口将项目添加到数组列表;
- 将geoJSON要素属性添加到Mapbox弹出窗口;
- 添加到编辑框弹出窗口;
- 将图标添加到 SlidingTabLayout 而不是文本;
- 将弹出窗口添加到闪亮的应用程序?;
- 如何添加到Android手机的“添加到主屏幕”弹出窗口;
- 将MarkerCluster添加到Google地图,而不是显示;
- matplotlib将矩形添加到图而不是轴;
- 将按钮添加到Mapboxgl.js中的弹出窗口;
- 将表单发布到弹出窗口而不是父窗口;
- 如何将子元素添加到ROOT;
- PWA 添加到主屏幕不显示弹出窗口;
- GmailApp - 将标签添加到特定邮件,而不是线程;
- 将“添加到购物车"链接而不是按钮;
- 导航抽屉:将标题添加到组而不是项目;
- 将控件添加到PropertySheet而不添加到PropertyPage;
- 将Target添加到Campaign而不先添加到库?;
- 将Sweet Alert弹出窗口添加到React组件中的按钮;
- 窗口将 Java 添加到路径;
其他开发最新文章
- 拒绝显示一个框架,因为它将'X-Frame-Options'设置为'sameorigin';
- 什么是&QUOT; AW&QUOT;在部分标志属性是什么意思?;
- 在运行npm install命令时获取'npm WARN弃用'警告;
- cmake无法找到openssl;
- 从Spark的scala中的* .tar.gz压缩文件中读取HDF5文件;
- Twitter :: Error :: Forbidden - 无法验证您的凭据;
- 我什么时候需要一个fb:app_id或者fb:admins?;
- 将.db文件导入R;
- npm通知创建一个lockfile作为package-lock.json。你应该提交这个文件;
- 拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src'self'”;