Angular-父容器内的打开底表(MatBottomSheet)

时间:2019-04-24 07:41:16

标签: angular angular-material bottom-sheet

我正在尝试在div容器中打开材料底页,默认情况下,它是作为主体内的最后一个元素打开的。

看着documentation,我需要使用viewContainerRef,但是我无法使其正常工作。

这与我正在尝试做的事情类似:

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

但是它似乎没有任何改变。

任何帮助将不胜感激。

预先感谢

1 个答案:

答案 0 :(得分:0)

似乎对viewContainerRef选项的真正含义有误解。

MatBottomsheet是使用ComponentPortal创建的。从ComponentPortal documentation,我们可以找到对viewContainerRef的更详细的描述:

附加组件应位于Angular的逻辑组件树中的位置。

这与组件呈现的位置不同

由PortalOutlet确定。当主机位于Angular应用程序上下文之外时,源是必需的。

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

  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 -我们的BottomSheet

现在,我们真正需要更改的是OverlayContainer,根据docs,它是:

所有单个叠加层元素都位于其中的容器元素 呈现。

默认情况下,覆盖容器直接附加到文档主体。

从技术上讲,可以提供一个自定义覆盖容器:

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

但是,不幸的是,它是一个 singleton ,并产生了一个新问题:

MatBottomSheetMatDialogMatSnackbarMatTooltip组件使用相同的OverlayContainer,因此所有这些组件都将在此自定义容器中打开。