Add directive to module after bootstrap and applying on dynamic content

I have a web page with a module defined (myModule) where I'm boostraping angularjs using

angular.bootstrap(element,[myModule.name]);

After the click of a button, I add dynamic html and compile using

$compile('<my-element data="data"></my-element>',$scope.$new());

The directive is added using

myModule.directive('myElement',function(){});

The problem is when I add the directive before calling bootstrap, $compile ends up correctly processing my directive. However, if the directive is added after calling bootstrap, $compile does not do anything to my html. It just adds the class ng-scope to it and the directive/tag is not processed.

In my case, not all the directives will be loaded before bootstrap is called. In the case where I load directives after calling bootstrap, how do I get to use it within the page?

Thanks.

Edit: Just to clarify. All directives are loaded dynamically. Those I load before bootstrapping work fine. Those I load after bootstrapping fails. When I swap the directives loaded, I can the same result so it is not the directives but appears to be that after bootstrapping, newly added directives does not seem to take effect.

The thing with registering lazy controller or directives is that you have to get hold of $controllerProvider and $compileProvider respectively.

It can be done only during configuration phase so you have to keep the references until you load the controllers/directives.

Lately I was working on lazy loading of the controller, today I've added support for directives, check out my code here:

https://github.com/matys84pl/angularjs-requirejs-lazy-controllers/

particularly this module lazy-directives.js

NOTE: I use RequireJS in my project, however applying my solution to yepnope should be quite easy.

This Fiddle show-cases how to dynamically load/register and use:

  • Angular controllers (using $controllerProvider)
  • Angular directives (using $compileProvider)
  • Angular partial templates (using $templateCache)

Code:

var app = angular.module('app', []);
app.config(function($controllerProvider, $compileProvider) {
        // see page 12 of:
        //    http://www.slideshare.net/nirkaufman/angularjs-lazy-loading-techniques
        app.lazyController = $controllerProvider.register;

        // see: http://jsfiddle.net/8Bf8m/33/
        app.lazyDirective = $compileProvider.directive;
    });

// set of partials
var partials = [];

// store scope & templateCache, so we can dynamically insert partials
var scope, templateCache;

// define main controller
function MainCtrl($scope, $templateCache) {
    $scope.partials = partials;

    scope = $scope;
    templateCache = $templateCache;
}

var maxPartials = 3;
var i = 0;

// add controllers, content & directives dynamically:
var timer = setInterval(function() {
    var i = partials.length;

    app.lazyDirective('clickMe', function () { return {
        link : function (scope, element) {
            element.bind('click', function () {
                alert('Clicked: ' + element.text());
            });
        },
    };});

    // define controller
    var ctrlName = 'partial' + i + 'Ctrl';
    app.lazyController(ctrlName, function($scope) {
        $scope.text = 'hi ' + i;
    });

    // add partial template that I have available in string form
    var newPartial = {
        name: 'template' + i,
        content: '<div ng-controller="' + ctrlName + '" class="a' + i + '">' +
        '<input type="text" ng-model="text"></input>'+
        '{{text}} <br/>' + 
        '<button click-me="">Click Me!</button>' +
        '</div> <br/> <br/>'
    };
    partials[i] = newPartial;

    // add template and notify angular of the content change
    templateCache.put(partials[i].name, partials[i].content);
    scope.$apply();

    // stop timer
    if (partials.length >= maxPartials)  clearInterval(timer);
}, 1000);