我正在使用这个tutorial来拥有一个定制的上下文菜单. 我正在显示列表中的项目,我希望当用户单击这些项目时,会显示它们的索引.目前,右击任何项目都会显示最后一个索引,例如,如果我的列表有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;
}

推荐答案

  1. We can move the <编码>context-menu outside the <编码>*ngFor because you only need a single 上下文菜单 for a table.
  2. To identify the selected index I am using <编码>data-id data attributes to identify which item was selected.

编码

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

    Const id=vent.get.parentElement.datet.id ?Event.target.parentElement.dataset.id :vent.Target.datet.id; Const finIndex=this.items.findIndex((X)=>;x=id); 如果(finIndex&>-1){ This.index=oundIndex;

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

<编码>this.printIndex(this.index);

双手

<编码>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,
    });
  }
}

stackblitz

Typescript相关问答推荐

强制两个类型脚本对象具有相同的键

APP_INITIALIZER—TypeError:appInits不是函数

单击并移除for循环中的一项也会影响另一项

为什么TypeScript假设文档对象始终可用?

泛型类型联合将参数转换为Never

如何消除在Next.js中使用Reaction上下文的延迟?

我可以使用TypeScrip从字符串词典/记录中填充强类型的环境对象吗?

类型脚本映射类型:从对象和字符串列表到键值对象

使用KeyOf和Never的循环引用

对于始终仅在不是对象属性时才抛出的函数,返回Never

从非文字数组(object.keys和array.map)派生联合类型

在打字脚本中对可迭代对象进行可变压缩

如何在Reaction 18、Reaction-Rout6中的导航栏中获取路由参数

如何键入并类型的函数&S各属性

类型判断数组或对象的isEmpty

带有';的类型脚本嵌套对象可选属性错误满足';

Select 类型的子项

我如何键入它,以便具有字符串或数字构造函数的数组可以作为字符串或数字键入s或n

如何限定索引值必须与相应属性的id字段相同

递归类型名称