Search code examples
angularjsangularjs-service

How can I register an angularjs factory after the app has "started" / been loaded?


I've got the guts of a routing architecture in Angular that will dynamically download and inject Angular Controllers and Services ... the Controller part works fine, and I'm trying to download dependant services via $route's .resolve property.

Now, say if I have a factory declared in scope while the page starts up, it registers fine and Controllers that use it resolve fine, e.g:

myModule.factory('MyInjectedDep', function() {
    return {};
});

....

MyController = function(MyInjectedDep)

But if I try and register that dependency at "run time" (for want of a better phrase), I get a Circular Dependency error. e.g:

$route.routes[routeItem.route] = {
   resolve: {
      MyInjectedDep: ['$injector', function($injector) {
          // In real code I download/eval this via $http but same behavior occurs
          myModule.factory('MyInjectedDep', function() {
              return {};
          });
      }]
   }
}

So when my Controller is then initiated:

MyController = function(MyInjectedDep)

I get a circular dependency error, but no dependency trace in the error message?

Error: Circular dependency:

Any ideas appreciated


Solution

  • The key is latching onto $provide at configuration time. If you grab $provide at configuration time and maintain a reference to it, you can use it to register your factory like:

    $provide.factory.apply(null, ['MyInjectedDep', [function() {
       return {};
    ]}]);
    

    I have a provider/service designed to do this, adapted from some other samples on github: https://github.com/afterglowtech/angular-couchPotato .

    It's primarily designed to load from AMD, but you could probably use it's registerXXX functions with $http, or at least copy the relevant portions of its code. Don't let the size of the repository fool you -- the actual provider/service is about one page of code https://github.com/afterglowtech/angular-couchPotato/blob/master/src/couchPotato.js .