组件:https://material.angular.io/components/snack-bar/examples
我有一个页面是父部分(“ #wrapper_container”)。我想在“ #wrapper_element”子元素的中心弹出小吃店。
谢谢
答案 0 :(得分:1)
是的。 viewContainerRef
的{{1}}属性将接受MatSnackBarConfig
用作将其ViewContainer
附加到其上的位置。
获取元素Portal
可以通过ViewChild查询或将其注入到放置在元素上的指令中来完成。前者是一个更简单的选择:
component.html:
ViewContainerRef
component.ts:
<div #wrapperContainer> </div>
答案 1 :(得分:1)
您应该检查他们的API,这里有参数viewContainerRef
,也可以用verticalPosition
定义高度。
答案 2 :(得分:1)
我们无法使用viewContainerRef
选项将快餐栏附加到自定义容器。在Angular Material docs中,此选项为:
出于依赖关系注入的目的,作为快餐栏的父级的视图容器。
注意:这不影响在DOM中插入快餐栏的位置。
从ComponentPortal
documentation,我们可以找到对viewContainerRef
的更详细的描述:
附加组件应位于Angular的逻辑组件树中的位置。 这与组件呈现的位置不同,后者是由PortalOutlet确定的。当主机位于Angular应用程序上下文之外时,源是必需的。
在打开快餐栏时检查DOM时,我们将找到以下组件层次结构:
Body
-<body>
OverlayContainer
-<div class="cdk-overlay-container"></div>
Overlay
-<div id="cdk-overlay-{id}" class="cdk-overlay-pane">
ComponentPortal
-<snack-bar-container></snack-bar-container>
Component
-我们的Snackbar
,其打开方式为:this.snackbar.open(message, action)
。现在,我们真正需要更改的是OverlayContainer
在DOM中的位置,根据docs,这是:
所有单个叠加层元素都位于其中的容器元素 呈现。
默认情况下,覆盖容器直接附加到文档主体。
从技术上讲,可以使用自定义提供程序来提供自定义覆盖容器,如documentation中所述:
@NgModule({
providers: [{provide: OverlayContainer, useClass: AppOverlayContainer}],
// ...
})
export class MyModule { }
但是,不幸的是,这是一个单例,并造成了潜在的问题:
MatDialog
,MatSnackbar
,MatTooltip
,MatBottomSheet
和所有使用OverlayContainer
的组件都将在此AppOverlayContainer中打开 :
由于这种情况远非理想,因此我编写的自定义提供程序(AppOverlayContainer
仅需要按需更改overlaycontainer
的位置。如果未调用,则将overlaycontainer
附加到body
上。
代码是:
import { OverlayContainer } from '@angular/cdk/overlay';
export class AppOverlayContainer extends OverlayContainer {
customContainerClass = 'app-overlay-container';
/**
* Append the OverlayContainer to the custom element
*/
public appendToCustomContainer(element: HTMLElement): void {
if (element === null) {
return;
}
if (!this._containerElement) {
super._createContainer();
}
// we need to add a custom css class
this._containerElement.classList.add(this.customContainerClass);
// this._containerElement is 'cdk-overlay-container'
// the code below attaches it to our custom container
element.appendChild(this._containerElement);
}
/**
* Remove the OverlayContainer from the custom element and append it to body
*/
public removeFromCustomContainer(): void {
if (!this._containerElement) {
return;
}
this._containerElement.classList.remove(this.customContainerClass);
// this._containerElement is 'cdk-overlay-container'
// the code below re-attaches it to body
this._document.body.appendChild(this._containerElement);
}
}
因此,在打开小吃店之前,我们必须致电:
AppOverlayContainer.appendToCustomContainer(HTMLElement).
方法,该方法将overlaycontainer
附加到我们的自定义包装元素。
小吃店关闭时,最好致电:
AppOverlayContainer.removeFromCustomContainer();
方法,该方法将从我们的自定义包装元素中删除overlaycontainer
,并将其重新附加到body
。
示例:
如果我们要在自定义容器中显示小吃店,#appOverlayWrapperContainer1
:
<button mat-raised-button
(click)="openSnackBar(appOverlayWrapperContainer1, 'Snackbar 1 msg', 'Action 1')">
Open Snackbar 1
</button>
<div class="app-overlay-wrapper-container" #appOverlayWrapperContainer1>
Snackbar 1 overlay attached to this div
</div>
在Ts中,我们有:
export class SnackBarOverviewExample {
constructor(
private _snackBar: MatSnackBar,
private _appOverlayContainer: OverlayContainer
) { }
openSnackBar(
appOverlayWrapperContainer: HTMLElement,
message: string,
action: string
) {
if (appOverlayWrapperContainer === null) {
return;
}
(this._appOverlayContainer as AppOverlayContainer).appendToCustomContainer(appOverlayWrapperContainer);
this.snackbarRef = this._snackBar.open(message, action, {
duration: 2000
});
}
}
此外,我们需要在应用程序通用样式表中插入一些CSS:
.app-overlay-container {
position: absolute;
}
完整代码和演示都在Stackblitz上,如果我已经实现了多个快餐栏容器:
https://stackblitz.com/edit/angular-wksbmf-s15ms4?file=src%2Fapp%2Fapp.component.ts