在 Angular 中自定义上下文菜单

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

我正在使用此教程来创建自定义上下文菜单。 我正在显示列表中的项目,我希望当用户单击这些项目时,显示它们的索引。目前,右键单击任何项目会显示最后一个索引,例如,如果我的列表有 3 个项目,则单击任何项目会显示 2! 如何显示每个项目的正确索引?

这是我的代码:

<div *ngFor="let item of items; let i = index" (contextmenu)="displayContextMenu($event); false">
    <span> {{item}}</span>
    <app-context-menu
        *ngIf="rightClickMenuItems.length > 0 && isDisplayContextMenu"
        [ngStyle]="getRightClickMenuStyle()"        
        [contextMenuItems]="rightClickMenuItems"
        (onContextMenuItemClick)="handleMenuItemClick($event, i)"
    ></app-context-menu>
</div>

ts 文件:

items = ["item0","item1","item2"];

isDisplayContextMenu!: boolean;
rightClickMenuItems: Array<ContextMenu> = [];

rightClickMenuPositionX!: number;
rightClickMenuPositionY!: number;

displayContextMenu(event: any) {
  this.isDisplayContextMenu = true;
  this.rightClickMenuItems = [
    {
      menuText: 'Print index',
      menuEvent: 'Handle print index',
    },
  ];

  this.rightClickMenuPositionX = event.clientX;
  this.rightClickMenuPositionY = event.clientY;
}

handleMenuItemClick(event: any, index: number) {
  switch (event.data) {
    case this.rightClickMenuItems[0].menuEvent:
      this.printIndex(index);
      break;
  }
}

printIndex(index: number){
  alert(index);
}

@HostListener('document:click')
  documentClick(): void {
  this.isDisplayContextMenu = false;
}

getRightClickMenuStyle() {
  return {
    position: 'fixed',
    left: `${this.rightClickMenuPositionX}px`,
    top: `${this.rightClickMenuPositionY}px`
  }
}

上下文菜单组件:

.html:

<ng-container>
    <div>
        <div *ngFor="let menuItem of contextMenuItems; index as i"
            (click)="onContextMenuClick($event, menuItem.menuEvent)">
            {{ menuItem.menuText }}
        </div>
    </div>
</ng-container>

.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { ContextMenu } from '../../_models/contextMenu.model';
import { NgIf, NgFor } from '@angular/common';

@Component({
    selector: 'app-context-menu',
    templateUrl: './context-menu.component.html',
    styleUrls: ['./context-menu.component.css'],
    standalone: true,
    imports: [NgIf, NgFor]
})

export class ContextMenuComponent {
    @Input() contextMenuItems!: Array<ContextMenu>;
    @Output() onContextMenuItemClick: EventEmitter<any> = new EventEmitter<any>();
    onContextMenuClick(event: any, data: any): any {
        this.onContextMenuItemClick.emit({
            event,
            data,
        });
    }
}

型号:

export interface ContextMenu {
    menuText: any;
    menuEvent: any;
}
angular typescript contextmenu
1个回答
0
投票
  1. 我们可以将
    context-menu
    移到
    *ngFor
    之外,因为您只需要一个表格的上下文菜单。
  2. 为了识别所选索引,我使用
    data-id
    数据属性 来识别选择了哪个项目。

代码

<div *ngFor="let item of items; let i = index" (contextmenu)="displayContextMenu($event); false"
    [attr.data-id]="item">
    <span> {{item}}</span>
  1. 我们可以访问属性来标识哪个项目被选择,我们可以只存储选定的索引,这里有两个选项将其存储在主组件中,或者您可以只将其存储在上下文菜单中。

    const id = event.target.parentElement.dataset.id ? event.target.parentElement.dataset.id : 事件.目标.数据集.id; const findIndex = this.items.findIndex((x) => x === id); if (foundIndex > -1) { this.index = 找到索引;

最后,我们可以使用警报打印索引!

this.printIndex(this.index);

main.ts

import { CommonModule } from '@angular/common';
import { Component, HostListener } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import {
  ContextMenu,
  ContextMenuComponent,
} from './context-menu/context-menu.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ContextMenuComponent],
  template: `
    <div *ngFor="let item of items; let i = index" (contextmenu)="displayContextMenu($event); false"
    [attr.data-id]="item">
    <span> {{item}}</span>
</div>
    <app-context-menu
        *ngIf="rightClickMenuItems.length > 0 && isDisplayContextMenu"
        [ngStyle]="getRightClickMenuStyle()"
        [contextMenuItems]="rightClickMenuItems"
        (onContextMenuItemClick)="handleMenuItemClick($event)"
    ></app-context-menu>
  `,
})
export class App {
  items = ['item0', 'item1', 'item2'];
  index = -1;

  isDisplayContextMenu!: boolean;
  rightClickMenuItems: Array<ContextMenu> = [];

  rightClickMenuPositionX!: number;
  rightClickMenuPositionY!: number;

  displayContextMenu(event: any) {
    const id = event.target.parentElement.dataset.id
      ? event.target.parentElement.dataset.id
      : event.target.dataset.id;
    const foundIndex = this.items.findIndex((x) => x === id);
    if (foundIndex > -1) {
      this.index = foundIndex;
      this.isDisplayContextMenu = true;
      this.rightClickMenuItems = [
        {
          menuText: 'Print index',
          menuEvent: 'Handle print index',
        },
      ];

      this.rightClickMenuPositionX = event.clientX;
      this.rightClickMenuPositionY = event.clientY;
    }
  }

  handleMenuItemClick(event: any) {
    switch (event.data) {
      case this.rightClickMenuItems[0].menuEvent:
        this.printIndex(this.index);
        break;
    }
  }

  printIndex(index: number) {
    alert(index);
  }

  @HostListener('document:click')
  documentClick(): void {
    this.isDisplayContextMenu = false;
  }

  getRightClickMenuStyle() {
    return {
      position: 'fixed',
      left: `${this.rightClickMenuPositionX}px`,
      top: `${this.rightClickMenuPositionY}px`,
    };
  }
}

bootstrapApplication(App);

上下文菜单

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { NgIf, NgFor } from '@angular/common';

export interface ContextMenu {
  menuText: any;
  menuEvent: any;
}

@Component({
  selector: 'app-context-menu',
  template: `
  <ng-container>
  <div>
    <div
      *ngFor="let menuItem of contextMenuItems; index as i"
      (click)="onContextMenuClick($event, menuItem.menuEvent)"
    >
      {{ menuItem.menuText }}
    </div>
  </div>
</ng-container>

  `,
  standalone: true,
  imports: [NgIf, NgFor],
})
export class ContextMenuComponent {
  private id!: string;
  @Input() contextMenuItems!: Array<ContextMenu>;
  @Output() onContextMenuItemClick: EventEmitter<any> = new EventEmitter<any>();
  onContextMenuClick(event: any, data: any): any {
    this.onContextMenuItemClick.emit({
      event,
      data,
    });
  }
}

堆栈闪电战

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