Patrioticcow Patrioticcow - 1 year ago 68
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);

Answer Source

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
                  console.log('Dynamic controller', $scope);
                  this.method = function() { return 123; };
              //these are the injected deps

For some example usage in a unit testing context, see:

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download