2

I'm trying to create a context menu directive for my angular application. I want this directive to be used for any element in the application that needs a context menu.

The problem is that in my app there are many 'user controls', that is - directives for extending buttons, inputs, grid etc. If I try to put the my-context-menu directive on any of them I get a multidir error, since both of the directives are defining templates.

The context menu directive looks something like this:

angular.module('myApp').directive('myContextMenu', function () {

    var myContextMenu= {};

    myContextMenu.restrict = 'A';

    myContextMenu.templateUrl = 'templates/myContextMenuTemplate.html';

    // Here I have scope and controller with all the functionality

    return myContextMenu;
});

Another directive for example:

angular.module('myApp').directive('myGrid', function () {

    var myGrid= {};

    myGrid.restrict = 'E';

    myGrid.templateUrl = 'templates/myGridTemplate.html';

    // Here I have scope, controller and link function with all the functionality

    return myGrid;
});

I want to have a context menu on the grid, and that in the grid directive I will be able to access the context menu controller.

What I tried is this: <my-grid id="grid" my-context-menu /> which failed as expected...

Do you have any solution or other idea on how to achieve this?

Thanks in advance!

My angular version: 1.3.8

3
  • 1
    This is difficult two answer, without knowing what the my-grid and context-menu templates look like. Isn't it possible to wrap the two, so that the context-menu appears in a grid element (e.g. <div>), and use transclude in the grid directive? context-menu would then of course be restrict: 'A'. It could look like this then <div class="grid-itm"><ul class="context-menu">...</ul></div> Commented Feb 11, 2015 at 10:00
  • Can you please elaborate a little more? I didn't understand how I can restrict it as attribute and refers to it as class. and more - how can I pass attributes from the grid scope to the context menu scope? Commented Feb 12, 2015 at 12:02
  • I'm sorry, but this was misleading. The elements with the classes are just meant to show the template html, simplified a lot. Maybe this fiddle explains it a bit better: http://jsfiddle.net/mjm8k2ao/. Unfortunately I didn't get it to work without using $parent, which is not very elegant. But maybe you come up with a final solution. Commented Feb 12, 2015 at 15:32

1 Answer 1

2

You can share controllers between directives writing the same controller on the controller attribute of the directive object. And you can use transclude to embed html inside a directive with its own template. https://docs.angularjs.org/api/ng/directive/ngTransclude

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

4 Comments

I'm trying to transclude the context menu in the grid template as you suggested, and it's really showing up nicely. Now I want to be able to handle the open event of the context menu in the controller of the grid, that is - I want to pass a function as an attribute to the context menu directive. Do you have any idea? I don't want to set the controller attribute since the grid has a controller of its own. Thanks again.
It is possible to pass functions into directives declaring an scope object and passing '&'. then you can bind the function on the template with ng-click or some other directive and it will execute on the scope where it was defined (the controller). Or maybe you could emit and event and lisen for it on the the controller. I partycallary find events fast an clean. Do not forget to clean the events on the $destroy event of your directive. You're welcome
I tried this, but there are two problems with this: First - When I create an isolated scope on the context menu directive - the transclution is not working at all. Second - even if I pass the function of the grid to the link function of the context menu directive - the attribute is undefined. what I did is something like this: '<my-grid><my-context-menu open="onOpen"></my-context-menu><my-grid>' where 'onOpen' is a function in the myGrid scope
If you want to you can try using $parse service to execute an expersions that you can get from the attrs.<your-attribute-name>.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.