上下文菜单定位在可滚动元素内(角度)

问题描述 投票:0回答:1

我正在使用 cdk-virtual-scroll-viewport 显示大量元素列表,如下所示

<cdk-virtual-scroll-viewport itemSize="115px" class="scrollable-card">
  <div *cdkVirtualFor="let project projects">
   <app-project-card [project]="project"></app-project-card>
  </div>
</cdk-virtual-scroll-viewport>

我在 app-project-card 组件中定义了一个上下文菜单,如下所示

<mat-card class='project-card' (contextmenu)="onRightClick($event)">
  //other elements inside which are irrelavant
</mat-card>

<div style="visibility: hidden; position: fixed;" [style.left]="menuTopLeftPosition.x"
  [style.top]="menuTopLeftPosition.y" [matMenuTriggerFor]="menu"></div>

<mat-menu #menu="matMenu">
  <button mat-menu-item (click)="onEdit(project.id)"><mat-icon>edit</mat-icon>Edit</button>
  <button mat-menu-item (click)="onDelete(project.id)"><mat-icon>delete_outline</mat-icon>Delete</button>
</mat-menu>

下面是我的 onRightClick 函数的代码。

onRightClick(event: MouseEvent) {
    event.preventDefault(); // Prevent the browser's default context menu
    // Set the position of the context menu
    this.menuTopLeftPosition.x = `${event.clientX}px`;
    this.menuTopLeftPosition.y = `${event.clientY}px`;
    // Open the context menu
    this.matMenuTrigger.openMenu();
  }

我面临的问题是我的上下文菜单没有显示在正确的坐标上。坐标似乎是相对于视口计算的,我不确定。

滚动视口会更改 y 坐标偏离的值。 x 坐标保持不变但已关闭。如果您需要更多背景信息,请告诉我。谢谢你

css angular angular-material scrollable custom-contextmenu
1个回答
0
投票

我觉得你的.html可以是这样的

<mat-card class="project-card">
  <mat-card-content>
    {{data()?.name}} {{data()?.id}}
    <div
      #menuTrigger="cdkContextMenuTriggerFor"
      class="fill example-standalone-trigger"
      (mouseup)="open(menuTrigger)"
      [cdkContextMenuTriggerFor]="menu"
    ></div>
  </mat-card-content>
</mat-card>

<ng-template #menu>
  <div class="example-menu" cdkMenu (closed)="open(null)">
    <button class="example-menu-item" cdkMenuItem>Refresh</button>
    <button class="example-menu-item" cdkMenuItem>Settings</button>
    <button class="example-menu-item" cdkMenuItem>Help</button>
    <button class="example-menu-item" cdkMenuItem>Sign out</button>
  </div>
</ng-template>

哪里

  .fill{
    position:absolute;
    top:0;
    bottom:0;
    width:100%;
  }
  .mat-mdc-card{
    position:relative;
  }

还有

export class CardComponent {
  data = input<{ id: number; name: string }>();
  menuOpened = output<CdkContextMenuTrigger | null>();
  open(menu: any) {
    if (menu)
      setTimeout(() => {
        this.menuOpened.emit(menu);
      });
    else this.menuOpened.emit(null);
  }
}

我制作了当菜单打开/关闭时发出触发器以允许在滚动时关闭(我真的很疯狂,因为对我(打开)和(关闭)事件不起作用。

“父母”喜欢

<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport" #scroller>
  <div *cdkVirtualFor="let item of items" class="example-item">
    <app-card [data]="item" (menuOpened)="trigger=$event" />
  </div>
</cdk-virtual-scroll-viewport>

还有

  trigger!: CdkContextMenuTrigger | null;
  @ViewChild('scroller', { static: true }) scroller!: CdkVirtualScrollViewport;
  items: any[] = Array(100)
    .fill('')
    .map((x, index) => {
      return { id: index, name: 'name ' + index };
    });
  constructor(private ngZone: NgZone) {}
  ngOnInit() {
    this.scroller
      .elementScrolled()
      .pipe(filter((_: any) => this.trigger != null))
      .subscribe((_) => {
        this.ngZone.run(() => {
          this.trigger?.close();
        });
      });
  }

stackblitz

© www.soinside.com 2019 - 2024. All rights reserved.