angularjs adding controllers at runtime

Angular is fantastic. I"ve been using it for a couple of projects lately and have been learning a lot. I had to solve a problem today that took quite a while to figure out, so I thought I'd post the solution here.

Normally you need to define all of your controllers, services, etc when the angular app is bootstrapped - IE you need to pre-load all of the scripts, regardless of what the current view is, etc.

It's easy enough to load additional scripts at runtime, but the .controller(xxxx) method call will not affect the app after it has been loaded - so your controller code won't run. (apparently not a bug - it's by design)

I"m working on a kind of plugin module system, where I wanted to inject the controller into the system at run-time. The idea is that I want the controller code to load at the same time the view code is loaded, in fact I want to define both the view and the controller in the same file:


<div ng-contoller="mycontroller">
<p>this is the view</p>
<p>some value fom controller:  {{somevalue}} 

// the 'app' has been defined globally (see below)
app.contoller('mycontroller', function ($scope){
    console.log('mycontoller loaded')
    $scope.somevalue = 'some value'

where that file is included into the current page with an ng-include:

<div ng-include="myfile.html">

(actually in the future I'll be loading the content from the database).

Out of the box, that doesn't work in angular. But by overriding the .controller method in the .config event, it's possible to have calls made to .controller work correctly after angular has completely loaded.

// ensure the 'app' is available globally = angular.module('myapp', [ ... modules ... ]);
app.config( ... other dependencies... , $controllerProvider){
  app._controller = app.controller
    app.controller = function (name, constructor){
      $controllerProvider.register(&lt;wbr />name, constructor);
      return (this);

The above code is not a fully working sample, just a simplified javascript translation of my original coffeescript code. But it's got the relevant bits correct. 🙂

The same approach would work for services and directives, although you'd use the $provide service instead of the $controllerProvider

This blog post was where I found the technique