角度CDK连接覆盖与滚动到容器



(这里是第一篇文章,请耐心等待(

我在一个容器中有一个表,在那里我显示了符合某些标准的行的图标。单击图标应该会打开一个覆盖以显示一些信息,即使我在容器内滚动,覆盖也应该保持打开状态。滚动最初跟随页面的主体,所以我开始创建一个自定义策略。但是,我无法让它跟随表格滚动。覆盖层粘在一个地方,不会相应地移动。

叠加生成如下。任何关于如何解决这一问题的建议都将不胜感激!

private createOverlay() {
const positionStrategy = this.overlay.position()
.flexibleConnectedTo(this.overlayorigin.elementRef)
.withFlexibleDimensions(false)
.withPush(false)
.withPositions([
{
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top'
},
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom',
}
]);

const overlayConfig = new OverlayConfig({
hasBackdrop: false,
scrollStrategy: this.overlay.scrollStrategies.reposition({autoClose: false}),
positionStrategy: positionStrategy
});


this._overlayRef = this.overlay.create(overlayConfig);
this._overlayRef.backdropClick().subscribe(_ => {
this._overlayRef.detach();
this.closeWarning.emit(true);
});

this._portal = new TemplatePortal(this.content, this.portal);
this._overlayRef.attach(this._portal);
}

我认为您在这里寻找的神奇之处可能是添加cdkScrollable指令,该指令可以应用于可滚动的父容器。

例如:

<div cdkScrollable>

这将标记容器为可滚动,并将其注册到ScrollDispatcher,以便重新定位滚动策略将拾取正在滚动的容器。

我没有您的MVP,但从您共享的代码来看,它似乎运行良好。

看看我使用您共享的代码和material.angular.io.中的一些片段创建的这个工作堆栈

import {
Overlay,
OverlayConfig,
OverlayRef
} from "@angular/cdk/overlay";
import {
TemplatePortal
} from "@angular/cdk/portal";
import {
DataSource
} from "@angular/cdk/table";
import {
Component,
ElementRef,
EventEmitter,
Output,
TemplateRef,
ViewChild,
ViewContainerRef
} from "@angular/core";
import {
BehaviorSubject,
Observable
} from "rxjs";
@Component({
selector: "cdk-overlay-basic-example",
templateUrl: "cdk-overlay-basic-example.html",
styleUrls: ["cdk-overlay-basic-example.css"]
})
export class CdkOverlayBasicExample {
@ViewChild("templatePortalContent")
templatePortalContent: TemplateRef < unknown > ;
@Output() closeWarning = new EventEmitter < boolean > ();
isOpen = false;
displayedColumns: string[] = [
"action",
"position",
"name",
"weight",
"symbol"
];
dataSource = new ExampleDataSource();
private _overlayRef: OverlayRef;
private _portal: TemplatePortal;
constructor(
private overlay: Overlay,
private _viewContainerRef: ViewContainerRef
) {}
click(overlayorigin: ElementRef, element: PeriodicElement) {
console.log(arguments);
element.isOpen = !element.isOpen;
if (element.isOpen) {
this.createOverlay(overlayorigin);
} else {
this._overlayRef.detach();
}
}
private createOverlay(overlayorigin: ElementRef) {
const positionStrategy = this.overlay
.position()
.flexibleConnectedTo(overlayorigin)
.withFlexibleDimensions(false)
.withPush(false)
.withPositions([{
originX: "start",
originY: "bottom",
overlayX: "start",
overlayY: "top"
},
{
originX: "start",
originY: "top",
overlayX: "start",
overlayY: "bottom"
}
]);
const overlayConfig = new OverlayConfig({
hasBackdrop: false,
scrollStrategy: this.overlay.scrollStrategies.reposition({
autoClose: false
}),
positionStrategy: positionStrategy
});
this._overlayRef = this.overlay.create(overlayConfig);
this._overlayRef.backdropClick().subscribe(_ => {
this._overlayRef.detach();
this.closeWarning.emit(true);
});
this._portal = new TemplatePortal(
this.templatePortalContent,
this._viewContainerRef
);
this._overlayRef.attach(this._portal);
}
}
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
isOpen ? : boolean;
}
const ELEMENT_DATA: PeriodicElement[] = [{
position: 1,
name: "Hydrogen",
weight: 1.0079,
symbol: "H"
},
{
position: 2,
name: "Helium",
weight: 4.0026,
symbol: "He"
},
{
position: 3,
name: "Lithium",
weight: 6.941,
symbol: "Li"
},
{
position: 4,
name: "Beryllium",
weight: 9.0122,
symbol: "Be"
},
{
position: 5,
name: "Boron",
weight: 10.811,
symbol: "B"
},
{
position: 6,
name: "Carbon",
weight: 12.0107,
symbol: "C"
},
{
position: 7,
name: "Nitrogen",
weight: 14.0067,
symbol: "N"
},
{
position: 8,
name: "Oxygen",
weight: 15.9994,
symbol: "O"
},
{
position: 9,
name: "Fluorine",
weight: 18.9984,
symbol: "F"
},
{
position: 10,
name: "Neon",
weight: 20.1797,
symbol: "Ne"
},
{
position: 11,
name: "Hydrogen",
weight: 1.0079,
symbol: "H"
},
{
position: 12,
name: "Helium",
weight: 4.0026,
symbol: "He"
},
{
position: 13,
name: "Lithium",
weight: 6.941,
symbol: "Li"
},
{
position: 14,
name: "Beryllium",
weight: 9.0122,
symbol: "Be"
},
{
position: 15,
name: "Boron",
weight: 10.811,
symbol: "B"
},
{
position: 16,
name: "Carbon",
weight: 12.0107,
symbol: "C"
},
{
position: 17,
name: "Nitrogen",
weight: 14.0067,
symbol: "N"
},
{
position: 18,
name: "Oxygen",
weight: 15.9994,
symbol: "O"
},
{
position: 19,
name: "Fluorine",
weight: 18.9984,
symbol: "F"
},
{
position: 20,
name: "Neon",
weight: 20.1797,
symbol: "Ne"
},
{
position: 21,
name: "Hydrogen",
weight: 1.0079,
symbol: "H"
},
{
position: 22,
name: "Helium",
weight: 4.0026,
symbol: "He"
},
{
position: 23,
name: "Lithium",
weight: 6.941,
symbol: "Li"
},
{
position: 24,
name: "Beryllium",
weight: 9.0122,
symbol: "Be"
},
{
position: 25,
name: "Boron",
weight: 10.811,
symbol: "B"
},
{
position: 26,
name: "Carbon",
weight: 12.0107,
symbol: "C"
},
{
position: 27,
name: "Nitrogen",
weight: 14.0067,
symbol: "N"
},
{
position: 28,
name: "Oxygen",
weight: 15.9994,
symbol: "O"
},
{
position: 29,
name: "Fluorine",
weight: 18.9984,
symbol: "F"
},
{
position: 30,
name: "Neon",
weight: 20.1797,
symbol: "Ne"
}
];
export class ExampleDataSource extends DataSource < PeriodicElement > {
data = new BehaviorSubject < PeriodicElement[] > (ELEMENT_DATA);
connect(): Observable < PeriodicElement[] > {
return this.data;
}
disconnect() {}
}
.container {
height: 400px;
overflow: auto;
border: 1px solid grey;
margin: 10px 0;
}
table {
width: 100%;
border-collapse: collapse;
}
td,
th {
padding: 5px;
}
.content {
margin: 5px 0;
background: green;
height: 1000px;
}
.overlay-info {
padding: 20px;
border: 1px solid #865e0b;
background-color: orange;
color: white;
font-size: 16px;
}
<div class="container">
<table cdk-table [dataSource]="dataSource" border="1">
<ng-container cdkColumnDef="action">
<th cdk-header-cell *cdkHeaderCellDef> Action </th>
<td cdk-cell *cdkCellDef="let element">
<button (click)="click(origin, element)" type="button" cdkOverlayOrigin #origin>
{{element.isOpen ? "Close" : "Open"}}
</button>
</td>
</ng-container>
<ng-container cdkColumnDef="position">
<th cdk-header-cell *cdkHeaderCellDef> No. </th>
<td cdk-cell *cdkCellDef="let element"> {{element.position}} </td>
</ng-container>
<ng-container cdkColumnDef="name">
<th cdk-header-cell *cdkHeaderCellDef> Name </th>
<td cdk-cell *cdkCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container cdkColumnDef="weight">
<th cdk-header-cell *cdkHeaderCellDef> Weight </th>
<td cdk-cell *cdkCellDef="let element"> {{element.weight}} </td>
</ng-container>
<ng-container cdkColumnDef="symbol">
<th cdk-header-cell *cdkHeaderCellDef> Symbol </th>
<td cdk-cell *cdkCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns"></tr>
<tr cdk-row *cdkRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<div class="container">
<div class="content">
This is a very very long content!
</div>
</div>
<div class="container">
<div class="content">
This is another very very long content!
</div>
</div>
<ng-template #templatePortalContent>
<div class="overlay-info">
This is information panel!
</div>
</ng-template>