如何Angular 4上下文菜单

时间:2017-08-15 22:21:13

标签: angular contextmenu

如何在angular 4中创建上下文菜单?不幸的是,html上下文菜单不起作用。

所以我想创建一个组件并在光标坐标处右键单击显示它,但是如何实现呢?

e.g。

<ul>
    <li (click)="showContextMenuComponent">example</li>
</ul

5 个答案:

答案 0 :(得分:25)

我发现你所有的解决方案都非常复杂且难以定制,因为我刚刚开始,我只想用组件和事件绑定来解决这个问题。 所以我的ContextMenu是一个输入值为x和y的组件,右键单击它的ParentComponent顶部显示:)

所以这是:

Parent.component.ts

 export class parentComponent {
      contextmenu = false;
      contextmenuX = 0;
      contextmenuY = 0;

      //activates the menu with the coordinates
      onrightClick(event){
          this.contextmenuX=event.clientX
          this.contextmenuY=event.clientY
          this.contextmenu=true;
      }
      //disables the menu
      disableContextMenu(){
         this.contextmenu= false;
      }

parent.component.html

<!-- your whole html is wrapped in a div so anywhere you click you disable contextmenu,
also the div is responsible for suppressing the default browser contextmenu -->
<div (click)="disableContextMenu()" oncontextmenu="return false;">
    <!-- this is the usage -->
    <ul>
        <li (contextmenu)="onrightClick($event)">right click me!</li>
    </ul>

    <!--you have to write this only once in your component-->
    <div *ngIf="contextmenu==true">
        <app-contextmenu [x]="contextmenuX" [y]="contextmenuY"></app-contextmenu>
    </div>
</div>

这是上下文菜单本身:

contextmenu.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-contextmenu',
})
export class ContextmenuComponent{

  constructor() { }


  @Input() x=0;
  @Input() y=0;

}

contextmenu.component.html

<div class="contextmenu" [ngStyle]="{'left.px': x, 'top.px': y}">
  this is your contextmenu content
</div>

contextmenu.component.css

.contextmenu{
    position: absolute;
}

您现在可以像往常一样使用组件来应用自己的动画,CSS样式等。 希望这可以帮助:)玩得开心!

答案 1 :(得分:6)

您可以尝试使用ngx-contextmenu库。查看演示here

  

如果您使用角度版本4,请考虑使用ngx-contextmenu@1.3.5

答案 2 :(得分:2)

解决方案:(已通过Angular 9测试):

在HTML中:

<div (click)="itemClicked($event);" (contextmenu)="itemClicked($event);"> 
  Click Me!!!
</div>

在TS中:

itemClicked($event) {
  console.log($event);
  /* Use the following properties to differentiate between left and right click respectively.
  * $event.type will be "click" or "contextmenu"
  * $event.which will be "1" or "3"
  */

  // To prevent browser's default contextmenu
  $event.preventDefault();
  $event.stopPropagation();

  // To show your modal or popover or any page
  this.openQuickDialog($event); // FYI, this line calls my other method to open Popover dialog.
}

Here is a live example使用棱角材质菜单。右键单击某个项目时,它将菜单的位置设置为鼠标位置并打开它。

我发布了这个答案;以防万一可能会帮助像我这样的人。

答案 3 :(得分:0)

我创建了一个带有组件的自定义上下文菜单,任何人都可以从中构建自己的想法。

这里是链接

https://github.com/ieammac/angular-4-custom-context-menu

答案 4 :(得分:0)

User9132 的GREAT解决方案上进一步构建(请参见上文),您可以动态构建上下文菜单。这样,您可以重复使用通用上下文菜单组件。

parent.component.html: 右键单击列表项。最后,允许处理选定的菜单项。

library(ggplot2)
library(shiny)

a <- c(1,2,3,4,5,6)    
b <- c(50,100,40,30,20,80)    

mydata <- cbind(a,b)    
mydata <- as.data.frame(mydata)

ui <- fluidPage (

  headerPanel("basic app"),

  sidebarPanel(

    sliderInput("slider",
                label = "Time elapsed",
                min = min(mydata$a),
                max = max(mydata$a),
                value = min(mydata$a), step = 1,
                animate =
                  animationOptions(interval = 200, loop = TRUE))
  ),
  mainPanel(
    plotOutput("plot")
  )
)

server <- function(input, output) {
  output$plot <- renderPlot({
    plotdata <- mydata[1:which(input$slider==mydata$a),]
    p <- ggplot(plotdata,aes(x = a,y = b))

    if(nrow(plotdata)==1) {
      p + geom_point()
    } else {
      p + geom_line()
    }

  })
}

parent.component.ts: 父级确定菜单项并作用于所选菜单项。我开始在屏幕上放置上下文菜单,以便它不会从屏幕上掉下来。也许这需要改进-不客气。

<div class="row mt-3 ml-1">
  <div class="col-11 col-sm-11 col-md-10" (click)="disableContextMenu()" oncontextmenu="return false;">
    <div class="geocache-list-height">
      <table id="geocaches-list" class="table">
        <tbody>
        <tr *ngFor="let geocache of mygeocaches" class="d-flex">
          ...
          <td class="col-1" (contextmenu)="onrightClick($event, geocache)"><i class="icon-ellipsis-vert"></i></td>
        </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>
<!--you have to write this only once in your component-->
<div *ngIf="contextmenu==true">
  <app-contextmenu [x]="contextmenuX" [y]="contextmenuY" [menuitems]="showMenuOptions()" (menuItemSelected)="handleMenuSelection($event)"></app-contextmenu>
</div>

contextmenu.component.html: 单击菜单项后,它将传播到父级以处理选择。

@Component({
    selector: 'app-geocache-list',
    templateUrl: './parent.component.html',
    styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
    errorMessage = '';

    contextmenu = false;
    contextmenuX = 0;
    contextmenuY = 0;
    contextMenuForGeocache: MyGeocache;
    innerWidth: any;
    innerHeight: any;

    constructor(...) { }

    ngOnInit() {
        // for determining where the put the context menu -- on the screen ;-) 
        this.innerWidth = window.innerWidth;
        this.innerHeight = window.innerHeight;
        ...
        }
    }

    showMenuOptions() {
        return 'Delete;Navigate;Edit;';
    }
    onrightClick(event, geocache: MyGeocache ) {
        this.contextmenuX = event.clientX - 100;
        this.contextmenuY = event.clientY;
        this.contextmenu = true;
        const menuHeight = this.showMenuOptions().split(';').length;
        const maxY = this.innerHeight - ( menuHeight * 30);
        if ( this.contextmenuY > maxY ) {
            this.contextmenuY = maxY;
        }
    }
    // disables the menu
    disableContextMenu() {
        this.contextmenu = false;
    }

    handleMenuSelection( menuselection: string) {
        if ( menuselection === 'Delete') {
            ...
        } else if ( menuselection === 'Navigate') {
            ...
        }
    }
}

contextmenu.component.ts:

<div class="contextmenu" [ngStyle]="{'left.px': x, 'top.px': y}">
  <ul class="list-group">
    <li class="list-group-item" *ngFor="let menuItem of theMenuItems">
      <span (click)="outputSelectedMenuItem( menuItem)">{{ menuItem }}</span>
    </li>
  </ul>
</div>