You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular自定义右键菜单:点击菜单项无法显示正确索引求助

问题描述

实现自定义右键菜单时,列表中任意条目右键点击后,点击菜单项总是显示最后一个条目索引(例如3个条目时始终显示2),需要让菜单项显示对应条目的正确索引。

现有代码

父组件 HTML

<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;
}
解决方案

问题根源

  1. 每个循环条目内都渲染了一个app-context-menu,右键点击时所有菜单都会显示(重叠后看似一个),但点击时传递的i是循环最后一次的索引值。
  2. Angular变更检测机制导致点击菜单项时,i已经指向最后一个条目。

修改步骤

  1. 将app-context-menu移到*ngFor循环外部,只渲染一个菜单实例。
  2. 在右键点击时保存当前条目的索引,而非在菜单项点击时传递索引。

修改后的代码

父组件 HTML

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

父组件 TS

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

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

rightClickMenuPositionX!: number;
rightClickMenuPositionY!: number;
currentIndex!: number; // 新增变量保存当前点击的条目索引

displayContextMenu(event: any, index: number) { // 新增index参数接收当前条目索引
  this.currentIndex = index; // 保存当前索引
  this.isDisplayContextMenu = true;
  this.rightClickMenuItems = [
    {
      menuText: 'Print index',
      menuEvent: 'Handle print index',
    },
  ];

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

handleMenuItemClick(event: any) { // 移除index参数
  switch (event.data) {
    case this.rightClickMenuItems[0].menuEvent:
      this.printIndex(this.currentIndex); // 使用保存的当前索引
      break;
  }
}

// 其余代码保持不变

这样修改后,右键点击任意条目时,会保存对应的索引,点击菜单项时就会弹出正确的条目索引。

内容的提问来源于stack exchange,提问作者user6781

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 13:27:47