Angular - 在父容器内打开底部工作表 (MatBottomSheet) [英] Angular - Open Bottom Sheet (MatBottomSheet) inside parent container

查看:20
本文介绍了Angular - 在父容器内打开底部工作表 (MatBottomSheet)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 div 容器内打开一个材质底部表,默认情况下它作为主体内的最后一个元素打开.

查看文档,我需要使用viewContainerRef,但我无法让它工作.

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

app.component.html:

<代码>...<div #container></div>...

app.component.ts:

导出类 AppComponent 实现 AfterViewInit {@ViewChild('container', { read: ViewContainerRef }) _container;...构造函数(私人bottomSheet:MatBottomSheet,) {}ngAfterViewInit() {this.bottomSheet.open(MySheetComponent, {panelClass: '我的模态',viewContainerRef: this._container,});}}

但似乎没有任何改变.

任何帮助将不胜感激.

提前致谢

解决方案

似乎对 viewContainerRef 选项的真正含义存在误解.

MatBottomsheet 是用 ComponentPortal 创建的.从 ComponentPortal 文档,我们可以找到更多viewContainerRef 的详细说明:

<块引用>

附加组件应该在 Angular 的逻辑组件树中的位置.

这与组件渲染的地方不同,

这是由 PortalOutlet 决定的.当宿主在 Angular 应用程序上下文之外时,原点是必需的.

在打开底部表单时检查 DOM 时,我们会发现以下组件层次结构:

  1. OverlayContainer -

    </div>
  2. 叠加 -

  3. ComponentPortal -
  4. Component - 我们的 BottomSheet.

现在,我们真正需要改变的是OverlayContainer,根据文档,是:

<块引用>

所有单独的叠加元素所在的容器元素呈现.

默认情况下,覆盖容器直接附加到文档正文.

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

@NgModule({提供者:[{提供:OverlayContainer,useClass:CustomOverlayContainer}],//...})导出类 MyModule { }导出类 AppOverlayContainer 扩展 OverlayContainer {受保护的_createContainer():无效{const 容器:HTMLDivElement = document.createElement('div');container.classList.add('app-overlay-container');const 元素: 元素 |null = document.querySelector('#custom-overlay-contaier');如果(元素!== 空){element.appendChild(容器);this._containerElement = 容器;}}}

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

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

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

解决方案

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.

这篇关于Angular - 在父容器内打开底部工作表 (MatBottomSheet)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆