44
votes

I'm still a debutant on Angularjs. I want to inject dynamically a dependency of a service (that I created) in my controller.

But when I code a service with dependencies, I got this error :

Error: Unknown provider: $windowProvider <- $window <- base64

This is the code of the controller.

var base64 = angular.injector(['servicesModule']).get('base64');
console.log("base64", base64.encode("my text will be encoded"));

This code works:

var servicesModule = angular.module('servicesModule', []);
servicesModule.factory('base64', function() {
    return {

        name: 'base64',
        readonly: false,

        encode: function(input) {
            return window.btoa(input);
        },

        decode: function(input) {
            return window.atob(input);
        }

    };

});

This code doesn't work :

var extModule = angular.module('ext', []);
extModule.factory('base64', ['$window', function($window) {
    return {

        name: 'base64',
        readonly: false,

        encode: function(input) {
            return $window.btoa(input);
        },

        decode: function(input) {
            return $window.atob(input);
        }

    };

}]);

Another problem is when the service is in the same module as the controller. If the module has dependencies, I doesn't work (I have $routeProvider dependence in my module config) :

Error: Unknown provider: $routeProvider from mainModule

var mainModule = angular.module('main', [],
    function($routeProvider, $locationProvider) {
        //Some routing code
    }
);

JS Fiddles

Same module with dependencies(controller + service) : http://jsfiddle.net/yrezgui/YedT2/

Different module with dependencies : http://jsfiddle.net/yrezgui/YedT2/4/

Different module without dependencies : http://jsfiddle.net/yrezgui/YedT2/5/

1
both of these examples should work. If they don't the issue must be someplace else. It would be great if you could provide jsFiddle which we could fix, so that we have the whole app, rather than a small snippet. - Misko Hevery

1 Answers

62
votes

Don't call angular.injector() -- this creates a new injector. Instead, inject the already-created $injector into your controller and use it:

So instead of:

var algoController = function($scope) {
    $scope.base64 = angular.injector(['main']).get('base64');
};

Do this:

var algoController = function($scope, $injector) {
    $scope.base64 = $injector.get('base64');
};

But most of the time you should inject your service directly, rather than dynamically, like so:

var algoController = function($scope, base64) {
    $scope.base64 = base64;
};

See also AngularJS dynamically inject scope or controller