Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 255
nilzen Avatar asked Jan 03 '14 17:01

nilzen


3 Answers

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>
like image 51
nilzen Avatar answered Sep 28 '22 16:09

nilzen


You can use RequireJS to do this. Something like:

$routeProvider.when('/:plugin',{
    templateUrl: 'plugins/' + plugin + '/index.html',
    controller: plugin + 'Ctrl',
    resolve: {myCtrl: function($q){
        var deferred = $q.defer();
        require('myCtrlFile',function(){
            deferred.resolve();
        });
        return deferred.promise;
    }}
});

You will also need to register the controller dynamically. By exposing your providers in the app config.

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

You controller file might then look like:

define(['app'],function(app){
    app.register.controller('myCtrl',MyCtrlFunction);
});

This is just the general idea. I use a similar implementation to the one described here

I also use ui-router. I'm not certain if behavior is the same with ngRoute.

like image 22
calebboyd Avatar answered Sep 28 '22 16:09

calebboyd


Here is some solution you can do for this code

$routeProvider.when('/:plugin', function(plugin) {
  templateUrl: 'plugins/' + plugin + '/index.html',
  controller: fun,
  loadFrom:"assets/controller/myJsController"// this is our custom parameter we are passing to controller to identify the remote controller file.
});

We will create a parent function for all controller and will call all controller within this function as per defined in route configuration (in loadFrom key of route configuration).

 function fun($scope, $http, $location, $timeout, $route) {
        $timeout(function () {
        var path = $route.current.loadForm;
        $http.get("${pageContext.servletContext.contextPath}/resource/controller/" + path + ".js")
                .then(function (rsp) {
                eval(rsp.data);
                });
        });
        };

in assets/controller/myJsController.js file the code will be as

(function($scope){
//the whole code for controller will be here.
   $scope.message="working."


 })($scope)

Only thing you have to remember that in parent function you have to use all dependencies.

like image 45
Ranjeet Rana Avatar answered Sep 28 '22 17:09

Ranjeet Rana