问题
I'm trying to open a material bottom sheet inside a div container, as default it's opening as the last element inside the body.
Looking at the documentation, I need to use the viewContainerRef
, but I can't make it work.
This is similiar to what I'm trying to do:
app.component.html:
...
<div #container></div>
...
app.component.ts:
export class AppComponent implements AfterViewInit {
@ViewChild('container', { read: ViewContainerRef }) _container;
...
constructor(
private bottomSheet: MatBottomSheet,
) {}
ngAfterViewInit() {
this.bottomSheet.open(MySheetComponent, {
panelClass: 'my-modal',
viewContainerRef: this._container,
});
}
}
But it doesn't seems to make any change.
Any help would be appreciated.
Thanks in advance
回答1:
It seems that there is a misunderstanding of what viewContainerRef
option really means.
The MatBottomsheet
is created with ComponentPortal
. From ComponentPortal
documentation, we can found a more detailed description of viewContainerRef
:
Where the attached component should live in Angular's logical component tree.
This is different from where the component renders,
which is determined by the PortalOutlet. The origin is necessary when the host is outside of the Angular application context.
When inspecting the DOM when a bottomsheet is opened, we'll find the following component hierarchy:
OverlayContainer
-<div class="cdk-overlay-container"></div>
Overlay
-<div id="cdk-overlay-{id}" class="cdk-overlay-pane">
ComponentPortal
-<bottom-sheet-container></bottom-sheet-container>
Component
- ourBottomSheet
.
Now, what we really need to change is 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:
@NgModule({
providers: [{provide: OverlayContainer, useClass: CustomOverlayContainer}],
// ...
})
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('#custom-overlay-contaier');
if (element !== null) {
element.appendChild(container);
this._containerElement = container;
}
}
}
but, unfortunately, it is a singleton and creates a new problem:
MatBottomSheet
, MatDialog
, MatSnackbar
, MatTooltip
components use the same OverlayContainer, so all these components will open within this custom container.
来源:https://stackoverflow.com/questions/55824759/angular-open-bottom-sheet-matbottomsheet-inside-parent-container