Search code examples
angularjsangularjs-controllerangular-routing

Load controller dynamically based on route group


Is it possible to load a controller, it's js file, and a template dynamically based on a route group? Psuedo code which doesn't work:

$routeProvider.when('/:plugin', function(plugin) {
  templateUrl: 'plugins/' + plugin + '/index.html',
  controller: plugin + 'Ctrl',
  resolve: { /* Load the JS file, from 'plugins/' + plugin + '/controller.js' */ }
});

I've seen a lot of questions like this one but none that loads the js file/controller based on a route group.


Solution

  • I managed to solve it inspired by @calebboyd, http://ify.io/lazy-loading-in-angularjs/ and http://weblogs.asp.net/dwahlin/archive/2013/05/22/dynamically-loading-controllers-and-views-with-angularjs-and-requirejs.aspx

    Using http://dustindiaz.com/scriptjs

    app.js

    app.config(function($controllerProvider, $compileProvider, $filterProvider, $provide) {
      app.register = {
        controller: $controllerProvider.register,
        directive: $compileProvider.directive,
        filter: $filterProvider.register,
        factory: $provide.factory,
        service: $provide.service
      };
    });
    

    Then i register the "load controller by group" route.

    $routeProvider.when('/:plugin', {
    
      templateUrl: function(rd) {
        return 'plugin/' + rd.plugin + '/index.html';
      },
    
      resolve: {
        load: function($q, $route, $rootScope) {
    
          var deferred = $q.defer();
    
          var dependencies = [
            'plugin/' + $route.current.params.plugin + '/controller.js'
          ];
    
          $script(dependencies, function () {
            $rootScope.$apply(function() {
              deferred.resolve();
            });
          });
    
          return deferred.promise;
        }
      }
    });
    

    controller.js

    app.register.controller('MyPluginCtrl', function ($scope) {
      ...
    });
    

    index.html

    <div ng-controller="MyPluginCtrl">
      ...
    </div>