With the new menu component it'd be nice if there was support for right click menus(context menus). There doesn't seem to be an easy way to do this right now.
@epelc after discussing with the team we aren't going to officially support the ability to overwrite the right-click menu as we think that can lead to confused users.
That being said, we will, in the future, support the ability to programmatically open md-menus using the $mdMenu service. Right now we haven't documented it, but you can use it. Check out the menu controller src to see how it is done. In brief, something like this should get you started:
var myCustomMenu = angular.element(`<div class="md-open-menu-container md-whiteframe-z2">
<md-menu-content>
...
</md-menu-content>
</div>`);
var RightClickMenuCtrl = {
open: function(event) {
$mdMenu.show({
scope: $rootScope.$new(),
mdMenuCtrl: RightClickMenuCtrl,
element: myCustomMenu,
target: event.target // used for where the menu animates out of
});
},
close: function() { $mdMenu.hide(); },
positionMode: function() { return { left: 'target', top: 'target' }; },
offsets: function() { return { top: 0, left: 0 }; }
};
Full disclosure, the API is definitely not stable and may be changed at any time. I don't foresee it needing to for a while, but I just want to give fair warning. Hope this helps!
@rschmukler thanks for looking into it. I realize it can be confusing for a website to override the right click menu but did overriding it for chrome apps come up in the discussion at all? It seems to be a bit more normal in them as they have a more app like feel.
@epelc I'll mention it to the team at standup, but since it's semi-edge case and enables people to do some bad things for the none-chrome-app type of site, my leaning is toward not supporting it at the _framework_ level. As I mentioned above, you can likely create your own RightClickMenu service by mocking out most of the functionality from the md-menu controller.
@rschmukler I used your suggested approach with a little bit of fiddling I managed to make it work with right click. :+1:
However I get a little bit different behaviour then I was expecting with right click menu positioning. The problem that I have that menu appears in position relative to element ( I guess) and with context menu it should appear where the button is clicked not relative to element. Is there a way to update menus positioning ? Any hints are helpful thanks.
(I am using your snippet and providing context menu event)
@Stamy you could potentially use the event in RightClickMenuCtrl.open to store the position and then do some math in RightClickMenuCtrl.offsets to have the menu position correctly. Hope that helps.
@Stamy can you please post your code in codepen or plunker so i can use it?
@EladBezalel after 0.10.1 is released I could share the code. Because there are a lot of bugs in 10.0 which are important and a lot of them will be probably fixed in a new version.
@Stamy I know 10.0 is not stable yet, i'd like to use it in a poc and i figured that if you already did it i'd like to see how..
@rschmukler @epelc I am needing this functionality as well for an application I am working on. To address the comment that it is confusing, in most cases you are using Angular for application development. That being said, when considering the user experience of an application, one would expect a 'contextual' menu in an application to actually be contextual, just look at google drive as a prime example. I vote we reconsider this issue as it can be extremely beneficial in use with applications which is what this module is developed for in the first place.
my use case is a bit different - I'd like to trigger the menu on an arbitrary (and pre-defined) DOM element. can this approach be applied for that? or is there a simpler way to do it?
this would be helpful indeed. i concur including on the framework level might not be in-line with the general goals of the system. but triggering actions using a long-press/right-click etc to show more options for power users is a pretty standard requirement. it should at least be easy to do on top of the generic menu (a simple gist/plunkr etc).
did anybody do this already ?
In a current project I wrote a workaround for this problem.
My solution was to add two directives. The first directive just binds a contextmenu event to the attached element. The second directive wraps the mdMenuCtrl and overwrites the offsets function.
.directive('mousepointMenu', function () {
return {
restrict: 'A',
require: 'mdMenu',
link: function($scope, $element, $attrs, mdMenuCtrl) {
var MousePointMenuCtrl = mdMenuCtrl;
$scope.$mdOpenMousepointMenu = function($event) {
MousePointMenuCtrl.offsets = function() {
return {
left: $event.offsetX,
top: $event.offsetY
};
};
MousePointMenuCtrl.open($event);
};
}
};
}
Example for usage of this directive:
<md-menu mousepoint-menu>
<md-button ng-contextmenu="$mdOpenMousepointMenu($event)">
Open
</md-button>
<md-menu-content>
...
</md-menu-content>
</md-menu>
Hope it will help someone ;-)
+1
Nice solution, @daviian!
I encountered some trouble when my right-click area wasn't positioned at the very left and top, which caused the menu to pop-up in a strange behavior/positions.
Switching to use $event.clientX and .clientY caused another bug where the offsets got appended to last shown position rather than using its new calculated values (made the menu to move a bit further for every time it got shown).
Anyhow, I'm sharing my slightly modified version in case it helps anyone facing the same problem:
.directive('mousepointMenu', [function(){
return {
restrict: 'A',
require: 'mdMenu',
link: function($scope, $element, $attrs, mdMenuCtrl){
var MousePointMenuCtrl = mdMenuCtrl;
var prev = { x: 0, y: 0 }
$scope.$mdOpenMousepointMenu = function($event){
MousePointMenuCtrl.offsets = function(){
var mouse = {
x: $event.clientX,
y: $event.clientY
}
var offsets = {
left: mouse.x - prev.x,
top: mouse.y - prev.y
}
prev = mouse;
return offsets;
}
MousePointMenuCtrl.open($event);
};
}
};
}])
it is not working for me
get something working with the help of @daviian solution. Thanks !
Any plnkr ?
I made a Codepen example if you are still interested @kerrop33
@lumalav - 馃憤 ! Would you mind posting your _Context Menu Popup_ CodePen in the Material Forum
Most helpful comment
In a current project I wrote a workaround for this problem.
My solution was to add two directives. The first directive just binds a contextmenu event to the attached element. The second directive wraps the mdMenuCtrl and overwrites the offsets function.
Example for usage of this directive:
Hope it will help someone ;-)