Patrioticcow Patrioticcow - 5 months ago 9
Javascript Question

How to create / instantiate AngularJs controllers on the fly?

I have a simple controller that works just fine:

app.controller('IndexController', ['$scope', obj.indexPage]);

var obj = {};
obj.indexPage = function ($scope) { // do controller stuff };


I also have an event function that i want to use to load/create/instantiate this controller:

// some callback, doesn't really matter
app.onPage('index', function () {

// load and run controller logic in here
app.controller('IndexController', ['$scope', obj.indexPage]);

}, obj);


there are some issues, like
Argument 'IndexController' is not a function, got undefined


Any ideas?

my solution:

app.controller('IndexController', ['$scope', function ($scope) {
var obj = {};
obj.indexPage = function (data) {

// do controller stuff

};

app.onPage('index', function (data) {
obj.indexPage(data);
}, obj);
});

Answer

Due to how the angular module system works, you can't instantiate controllers asynchronously like that. You can however, use the $controller service to create controllers on the fly. The same technique below is often used in unit testing.

For example:

angular.module('app', [])

.controller('MyCtrl', function($rootScope, CtrlFactory){
    var dynamicCtrl = CtrlFactory.create({$scope: $rootScope.$new()});
    console.log(dynamicCtrl.method()); //-> 123
})

.factory('CtrlFactory', function($controller) { 
  return {
      create: function(locals) {
          return $controller(
              //this is the constructor of the new controller
              function($scope){
                  console.log('Dynamic controller', $scope);
                  this.method = function() { return 123; };
              }, 
              //these are the injected deps
              locals 
          );
      }
  };
})

For some example usage in a unit testing context, see: https://docs.angularjs.org/guide/controller.

I'll add that you may want to reconsider your reasons for doing this--I can't say I've seen $controller used outside testing.