Feature Request: Programmatically add directives to another directive's elements before they get compiled. #6950
Description
I ran into an issue. So far as I know, Angular doesn't have a mechanism by which to address it easily.
http://ngmodules.org has some awesome modules. They are really easy to use, but if they don't expose any events to you, then you're out of luck if you don't want to actually modify the 3rd party module's source code.
What if Angular had an easy way to attach directives to the element of another directive programmatically
(before it and any sub-templates get compiled) so that one could use third party directives and not worry if they've exposed any useful features like like event handling mechanism (e.g. they don't use ngClick on any elements)?
For example, here's an example:
Suppose we use someone's awesomeDirective
.
<div data-awesome-directive="awesome.data"></div>
This nice directive generates some type of awesome HTML widget with HTML that is defined in the 3rd party source code, perhaps a twitter feed, a profile badge, or something else awesome, but the author of the directive did not include any way to handle click events, etc!
We could step away from Angular, and use jQuery to make a click handler like
$("#awesomeWidget").on("click", function() {/* ... */});
but we don't want to leave the world of Angular awesomeness!
Perhaps, a new addition to the Module.directive
API can be added to Angular so one can add a directive to any other directive's elements, like so:
angular.element(document).ready(function() {
// create your app with a dependency on a 3rd party module.
var myApp = angular.module("myApp", ["awesomeModuleContainingAwesomeDirective"]);
// the 3rd party module contains an awesomeDirective.
// create a custom directive:
myApp.directive("customDirective", function() {
return { // set up directive properties like normal.
restrict: "A",
scope: {/* ... */},
// etc...
};
});
// attach the custom directive to the elements of another directive:
myApp.directive("awesomeDirective") // get the directive.
.attachDirective(".elements", "customDirective");
// the first argument to attachDirective() is a standard jQuery selector.
// internally, Angular would use jQuery's .find(".element")
// add an already-existing directive to the elements of another directive:
var awesomeDirective = myApp.directive("awesomeDirective"); // gets the directive.
awesomeDirective.attachDirective(".otherElements", "ngCloak");
// use a third argument for directives that accept an attribute expression:
awesomeDirective.attachDirective("#oneElement", "ngClick", "count = count + 1");
angular.bootstrap(document, ["myApp"]);
/*
* This would be absolutely pure awesome.
*/
});
This would be a nice way to extend directives that you are using in your app... But what if you want to attach directives to only specific instances of another directive? Then:
myApp.directive("awesomeDirective") // gets the directive.
.attachDirective([".rootElements", ".elements"], 'ngClick', "count = count + 1");
// ^ still no more than 3 arguments
The first argument in this case is an array. The first element in the array tells Angular that we wish to attach our directive to elements matching the awesomeDirective
only if those elements are .rootElements
. All .rootElements
that match the awesomeDirective
will then have the ngClick
directive applied to sub elements of the class elements
using jQuery's .find('.elements')
.
Angular could benefit from something like this! And it would not only be useful for event handling that 3rd party modules haven't exposed, but for augmenting 3rd party directives with all sorts of other functionality.