75

Is there a way to have an element set up so that it performs one action on left-click (ng-click) and then another action on a right-click?

Right now I have something like:

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

And I'd like to also be able to right click on the span to perform the function decrement();

4 Answers 4

141

You can use a directive to bind specific action on right click, using the contextmenu event :

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});
            });
        });
    };
});

Code example on fiddle

Sign up to request clarification or add additional context in comments.

7 Comments

This works great, but if I try to open a new window from the handler it gets blocked when triggered by right click and not when triggered by left click. I'm on chrome. jsfiddle.net/aslakhellesoy/QLHUV/3
@AslakHellesøy Probably because the browser doesn't recognise the ng-right-click directive as a user-initiated event.
@AslakHellesøy Works for me in Chrome (version 34.0.1847.116 m)
@Jer, you can have access to the event with $event, look at this example: jsfiddle.net/b0sx1ae1
Great answer, though I prefer to call it ngContextmenu (also change attrs.ngContextmenu and use like ng-contextmenu="...") because it handles the contextmenu, and not a right-click, which should be handled by ng-mousedown, ng-mouseup and ng-click.
|
31

Hi this is an old question but I have a solution that I think may be simpler in some cases. The ngMousedown (and ngMouseup) directives are triggered by the right mouse button and have access to the original mouse event through $event so you could do it this way:

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

Then in the controller, you can do the following:

$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;
    }
}

Here is a working fiddle. It works the same as the accepted answer but doesn't require the creation of a whole new directive. Although a directive may be a better solution, especially if you plan to attach right-click functions to lots of things. But anyway, another option.

3 Comments

Pretty cool, thanks. For anyone having problems with it, the oncontextmenu attribute has to be exactly on the right clicked element. Had it on the container and the context menu kept opening. (Chrome 51.0.2700.0 dev-m)
@Termi2610 works for me with the oncontextmenu on the container. chrome version : 54.0.2840.71
@yannick1976 Just tested it with my current version (53.0.2785.143 m) with the same container I used in april. And yes, it works. Seems like it was a bug in the version I used before.
7

One way is using a directive that binds an event handler to contextmenu event. I had hard time stopping bubbling to prevent default menu to show up so added native script handler for document. Tried with e.stopPropagation(), e.preventDefault() , return false etc . Checking for target in document handler seems to work well

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>

DEMO http://plnkr.co/edit/k0TF49GVdlhMuioSHW7i

Comments

1

You can use this directive.

<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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.