如何处理angular.js中的右键单击事件?


69

有没有一种方法可以设置一个元素,使其在左键单击(ng-click)上执行一个动作,然后在右键单击上执行另一个动作?

现在我有类似的东西:

<span ng-click="increment()">{{getPointsSpent()}}</span>

而且我还希望能够在跨度上单击鼠标右键以执行函数decrement();。

Answers:


138

您可以使用指令,通过contextmenu事件来绑定右键单击时的特定操作:

app.directive('ngRightClick', function($parse) {
    return function(scope, element, attrs) {
        var fn = $parse(attrs.ngRightClick);
        element.bind('contextmenu', function(event) {
            scope.$apply(function() {
                event.preventDefault();
                fn(scope, {$event:event});
            });
        });
    };
});

小提琴上的代码示例


这很好用,但是如果我尝试从处理程序中打开一个新窗口,则在右键单击触发时将被阻止,而在单击鼠标左键时则不会被阻止。我在镀铬。jsfiddle.net/aslakhellesoy/QLHUV/3
AslakHellesøy

@AslakHellesøy可能是因为浏览器无法将ng-right-click指令识别为用户启动的事件。
Magne 2014年

@AslakHellesøy在Chrome中为我工作(版本34.0.1847.116 m)
Martin

1
@Jer,您可以使用$ event来访问事件,请看以下示例:jsfiddle.net/b0sx1ae1
Bastien Caudan

2
伟大的答案,但我更喜欢称它为ngContextmenu(也改变attrs.ngContextmenu和类似用途ng-contextmenu="..."),因为它处理文本菜单,而不是右键单击,应当由办理ng-mousedownng-mouseupng-click
MicroVirus '16

27

您好,这是一个古老的问题,但是我有一个解决方案,我认为在某些情况下可能会更简单。ngMousedown(和ngMouseup)指令由鼠标右键触发,并可以通过其访问原始鼠标事件,$event因此您可以通过以下方式进行操作:

<span ng-mousedown="handleClick($event)"
      oncontextmenu="return false">  <!-- use this to prevent context menu -->
          {{getPointsSpent()}}
</span>

然后,在控制器中,您可以执行以下操作:

$scope.handleClick(evt) {
    switch(evt.which) {
        case 1:
            increment(); // this is left click
            break;
        case 2:
            // in case you need some middle click things
            break;
        case 3:
            decrement(); // this is right click
            break;
        default:
            alert("you have a strange mouse!");
            break;
    }
}

这是工作中的小提琴。它的工作原理与接受的答案相同,但不需要创建一个全新的指令。尽管指令可能是更好的解决方案,尤其是如果您打算将右键单击功能附加到很多东西上,则尤其如此。但是无论如何,另一种选择。


太酷了,谢谢。对于任何对此有疑问的人,oncontextmenu属性必须完全在右键单击的元素上。在容器上放置它,上下文菜单保持打开状态。(Chrome 51.0.2700.0 dev-m)
Daniel Z.

1
@ Termi2610通过容器上的oncontextmenu为我工作。chrome版本:54.0.2840.71
yannick1976 '10 -10-26

@ yannick1976刚刚用我当前的版本(53.0.2785.143 m)对其进行了测试,并使用了我在4月使用的相同容器。是的,它有效。好像是我以前使用的版本中的错误。
Daniel Z.

7

一种方法是使用将事件处理程序绑定到contextmenu事件的指令。我很难停止冒泡,以防止出现默认菜单,因此为添加了本机脚本处理程序document。试图用e.stopPropagation()e.preventDefault()return false等。在文档处理程序中检查目标似乎运行良好

app.directive('rightClick',function(){
    document.oncontextmenu = function (e) {
       if(e.target.hasAttribute('right-click')) {
           return false;
       }
    };
    return function(scope,el,attrs){
        el.bind('contextmenu',function(e){
            alert(attrs.alert);               
        }) ;
    }
});
<button right-click alert="You right clciked me">Right click me</button>

演示http://plnkr.co/edit/k0TF49GVdlhMuioSHW7i


1

您可以使用此指令

<div ng-controller="demoCtrl" save-content="classic-html">
  <div contextmenu="{{lists}}" class="box" click-menu="clickMenu(item)" right-click="rightClick($event)">
    <span>normal dropmenu</span>
  </div>
</div>

<script type="text/javascript">
angular.module('demo', ['ngContextMenu'])

  .controller('demoCtrl', ['$scope', function($scope) {
    $scope.lists = [{
      name: '11'
    }, {
      name: '22'
    }]

    $scope.clickMenu = function (item) {
      console.log(item);
    };

    $scope.rightClick = function (event) {
      console.log(event);
    };
  }])
</script>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.