0

I have a <ul> as such with <li>'s:

    <li ng-repeat="x in xs" ng-class-odd="'x'" ng-class-even="'y'">
    // inject here
        <span>
            {{x.v}}
        </span>
    </li>

I'd like on a certain event to inject a context menu (DOM position described above) that looks like this:

        <ul id="context" class="col">
            <li class="three"><span>1</span></li>
            <li class="three"><span>2</span></li>
            <li class="three"><span>3</span></li>
        </ul>

What's the best way to implement this? 1, 2 and 3 above have the same functions to handle the repeated list items in the parent container. So I'm not sure if injecting the context menu as described above is a smart idea since It would generate unseeded repetitions of the context menu.

Thanks.

5
  • Wouldn't be hard to have a contextmenu directive inserted in body that listens for $rootscope broadcast of mouse location and item x. Bind another directive to your repeating elements that has the contextmenu event handler in it and does the broadcast Commented Jan 10, 2015 at 22:34
  • @charlietfl can you please show me an example? Thanks. Commented Jan 10, 2015 at 22:39
  • You could use a contextmenu directive that is already available open source or you could just create one on your own. check this out github.com/ianwalter/ng-context-menu, github.com/Wildhoney/ngContextMenu Commented Jan 10, 2015 at 22:41
  • Hi thanks, this looks great. However, i'd like to inject the partial using hammer-swipe instead of right clicking... Commented Jan 10, 2015 at 22:48
  • Here: body.bind('click', function onClick() { // Remove all of the open context menus. scope.$apply(contextMenu.cancelAll); }); Can i edit this to make it work with hm-swipe instead of click? Commented Jan 10, 2015 at 23:08

1 Answer 1

1

Here's a really basic example of a set of contextmenu directives where menu is inserted once in body.

One directive is used to bind the contenxtmenu event and send data to the directive that controls the menu itself.

The item selected and the mouse position get passed as data in the broadcast

HTML

  <ul>
    <li ng-repeat="item in items" context="item">{{item.title}}</li>
  </ul>

  <ul menu id="context" ng-show="menu_on">
    <li ng-click="itemAlert('id')">Alert ID</li>
    <li ng-click="itemAlert('title')">Alert Title</li>
  </ul>

JS

app.directive('context', function($rootScope) {
  return {
    restrict: 'A',
    scope: {
      item: '=context'
    },
    link: function(scope, elem) {
      elem.bind('contextmenu', function(evt) {
        evt.preventDefault();
        var data = {
          pos: { x: evt.clientX, y: evt.clientY},
          item: scope.item
        }
        scope.$apply(function(){
          $rootScope.$broadcast('menu', data);
        });

      });
    }
  }
})

 app.directive('menu', function($rootScope) {
  return {
    restrict: 'A',
    link: function(scope, elem) {
      scope.$on('menu', function(evt, data) {
        scope.menu_on = true;
        scope.item = data.item;
        var cssObj = {
          left: data.pos.x + 20 + 'px',
          top: data.pos.y - 40 + 'px'
        };
        elem.css(cssObj)
      });
      scope.itemAlert = function(prop) {
        scope.menu_on = false;
        alert(scope.item[prop])
      }
    }
  }
});

Would need some additional document listeners to close menu when user clicks outside of it. Objective here was to just create basic mechanics of being able to display menu and pass data.

I haven't looked but there are probably some open source directives already available that are far more advanced than this.

DEMO

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

3 Comments

amazing answer.. I am giving it a try, but please note that I am not activating the contextmenu with right-click but with Hammer.js swipe event. How can this be adapted?
Don't know hammer but if it binds event handlers to elements would be same principle as the way I used 'bind'
Doesn't answer the question directly, but put me on the right track to complete the directive. Thanks!

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.