角CDK将覆盖与滚动滚动到容器

时间:2018-11-25 20:25:56

标签: angular scroll overlay 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);
}

1 个答案:

答案 0 :(得分:1)

我没有您的MVP,但是从您共享的代码来看,它似乎工作正常。

看看我使用您共享的代码和来自material.angular.io的几段内容创建的stackblitz

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>