Angularjs - context menu on a table cell

1.4k views Asked by At

I need to implement a context menu when I click on a table cell. I have tried this module which looks nice : https://github.com/ds82/angular-contextmenu
But when I m trying to use it :

    <table class="table table-bordered" contextmenu-container="main.contextmenu">
                    <tbody>
                        <tr ng-repeat="facture in factures"   contextmenu-item="facture">

...

I am getting this error on right click event :

TypeError: undefined is not a function at http://localhost:8080/assets/js/directives/contextmenu.js:74:27

The directive in error is :

app.directive('contextmenuItem', [function() {
  return {
    restrict: 'A',
    require: '^contextmenuContainer',
    scope: false,
    link: function( $scope, $element, $attrs, contextMenuCtrl ) {

      var iam = $scope[( $attrs.contextmenuItem )];
      $element.on( pointerEvents, function( event ) {
        $scope.$apply(function() {
          contextMenuCtrl.open( iam, event );
        });
        event.stopPropagation();
        return false;
      });
    }
  }
}]);

It crashes at this line :

contextMenuCtrl.open( iam, event );

Does anybody uses this module? Is it a known issue?

1

There are 1 answers

4
Pankaj Parkar On

Currently your problem is you are passing facture object inside attribute, which is one of the element, you will never have facture variable available inside a scope because it is a part of factures. Thats why when you are doing var iam = $scope[( $attrs.contextmenuItem )]; the value of iam gets undefined.

The reason behind it crashes at line contextMenuCtrl.open( iam, event ); because your contextMenuCtrl doesn't have method open in that directive controller

I'd suggest you to pass use isolated scope as you want to keep a track on the facture which are rendered using ng-repeat, then your isolated scope would have facture : '=' that will pass facture object to directive

Directive

app.directive('contextmenuItem', [function() {
  return {
    restrict: 'A',
    require: '^contextmenuContainer',
    scope: {
       facture: '='
    },
    link: function( $scope, $element, $attrs, contextMenuCtrl ) {

      //var iam = $scope[( $attrs.contextmenuItem )];
      $element.on( pointerEvents, function( event ) {
        $scope.$apply(function() {
          //`contextMenuCtrl` should have method open in its controller
          contextMenuCtrl.open( $scope.facture, event ); 
        });
        event.stopPropagation();
        return false;
      });
    }
  }
}]);

Your contextmenuContainer directive code should be like below.Must have controller associated with that directive and that must contain open method defined in scope.

contextmenuContainer Directive

app.directive('contextmenuContainer', [function() {
    return {
        restrict: 'A',
        scope: {},
        link: function($scope, $element, $attrs, contextMenuCtrl) {
            //if its there you can have code here
        },
        controller: function($scope) { //this must be here-
            //the methods defined here will be exposed to the directive  
            //which inherits it using require.
            $scope.open = function() {
              //code here
            };
            //you could have other methods to.
        }
    }
}]);