Angular - Open Bottom Sheet (MatBottomSheet) inside parent container

*爱你&永不变心* 提交于 2021-02-19 02:53:09

问题


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:

  1. OverlayContainer - <div class="cdk-overlay-container"></div>
  2. Overlay - <div id="cdk-overlay-{id}" class="cdk-overlay-pane">
  3. ComponentPortal - <bottom-sheet-container></bottom-sheet-container>
  4. Component - our BottomSheet.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!