59

Currently in app.js i have the following routes:

var gm = angular.module('gm', ['gm.services','gm.directives','gm.filters','gm.controllers','ngSanitize']);

gm.config(['$routeProvider', 'Path', function($routeProvider, Path) {

    $routeProvider.when('/login', { 
        templateUrl: Path.view('application/authentication/login.html'), 
        controller: 'authController' 
    });

    $routeProvider.when('/dashboard', { 
        templateUrl: Path.view('application/dashboard/index.html'), 
        controller: 'dashboardController' 
    }); 

    $routeProvider.otherwise({ 
        redirectTo: '/login'
    });

}]);

I'm trying to inject the Path dependency as you can see. Although i get an error saying it can't find this provider. I think this is because config module providers are executed first before anything else. below is my Path provider definition in "services.js"

gm.factory("Path", function() {
  return {
    view: function(path) {
      return 'app/views/' + path; 
    },
    css: function(path) {
      return 'app/views/' + path; 
    },
    font: function(path) {
      return 'app/views/' + path; 
    },
    img: function(path) {
      return 'app/views/' + path; 
    },
    js: function(path) {
      return 'app/views/' + path; 
    },
    vendor: function(path) {
      return 'app/views/' + path; 
    },
    base: function(path) {
      return '/' + path; 
    }
  }
}); 

how can i inject this provider into a config module?

Cadis
  • 35
  • 5
AndrewMcLagan
  • 13,459
  • 23
  • 91
  • 158

4 Answers4

84
  1. angular.config only accepts Providers
  2. every service, factory etc are instances of Provider

So to inject a service in config you just need to call the Provider of the service by adding 'Provider' to it's name.

angular.module('myApp')
  .service('FooService', function(){
    //...etc
  })
  .config(function(FooServiceProvider){
    //...etc
  });

According to the angularjs Provider documentation

... if you define a Factory recipe, an empty Provider type with the $get method set to your factory function is automatically created under the hood.

So if you have a factory (or service) such as:

.factory('myConfig', function(){
  return {
    hello: function(msg){
      console.log('hello ' + msg)
    }
  }
})

You first need to invoke your factory using the $get method before accessing the returned object:

.config(function(myConfigProvider){
   myConfigProvider
     .$get()
     .hello('world');
});
Ashish Kamble
  • 2,555
  • 3
  • 21
  • 29
vilsbole
  • 1,922
  • 1
  • 18
  • 22
  • 2
    I have a factory that I've done this with, but none of the methods are available. Any ideas? – binarygiant Dec 02 '14 at 23:08
  • 3
    i updated the answer to give an example how to access your factory methods. I hope it helps. – vilsbole Jan 29 '15 at 15:06
  • Your answer is wrong, see http://stackoverflow.com/a/24714452/1154692 "You can only inject Providers (not instances) into config blocks " – Marwen Trabelsi Apr 26 '15 at 17:25
  • 3
    @SmartyTwiti Yes exactly, can inject the Provider of your service/factory into the config block. Here is a working jsfiddle to demonstrate: http://jsfiddle.net/vefatkwL/ – vilsbole May 05 '15 at 17:28
  • I might be wrong, but I guess it's wrong to call `.$get()` manually, as service stops being a singleton. – Serhii Holinei Apr 11 '16 at 10:48
  • What if my service returns data that i want to use inside my component (angular 1.5.8) ? when I try `ctrl.xxx = provider.$get().funcName()` i'm getting an error that **ctrl is undefined** – gilad Nov 23 '16 at 16:07
  • @gilad, in view of the syntax, i suspect your trying to access your service in a controller, in which case you can call your service directly without using 'provider'. Regarding your error, if you define your object first, you will then be able to assign a property to it (ie. `var ctrl = {}`). If you've just got started with angular, i suggest you read about [controllerAs](https://github.com/johnpapa/angular-styleguide/tree/master/a1#controlleras-view-syntax) best practices – vilsbole Nov 24 '16 at 23:40
  • This, BY FAR, is the cleanest and simplest solution! Thanks! +1 – rolinger Apr 25 '21 at 18:27
58

In .config you can only use providers (e.g. $routeProvider). in .run you can only use instances of services (e.g. $route). You have a factory, not a provider. See this snippet with the three ways of creating this: Service, Factory and Provider They also mention this in the angular docs https://docs.angularjs.org/guide/services

Eduard Gamonal
  • 8,023
  • 5
  • 41
  • 46
  • 1
    This answer gives explanation, Tongamite's gives a solution. – Marwen Trabelsi Apr 26 '15 at 16:18
  • Isn't this answer 'now' wrong since it is possible to inject the factory in config by appending 'Provider' (as per the other answer ) – sumeet Aug 28 '15 at 08:51
  • Hi @sumeet can you elaborate more? angular appends Provider to your service name if you define one. this has happened since the jurassic. The other answer is basically using a Provider of a service in the config part. – Eduard Gamonal Aug 28 '15 at 09:29
  • 3
    what @sumeet says is you can inject factory in config BUT use it with `yourFactoryProvider.$get().yourFunction()`. – Dark Cyber Jan 08 '17 at 11:23
14

You should use constant for that, because it's the only thing you can inject in the config phase other than providers.

angular.module("yourModule").constant("paths", {
  base: function(){ ... }
});
Besnik
  • 6,469
  • 1
  • 31
  • 33
Shai Reznik - HiRez.io
  • 8,748
  • 2
  • 33
  • 33
  • ah perfect! so its possible for a constant to have functions? i thought they could only return strings..? – AndrewMcLagan Jul 05 '13 at 10:08
  • Yes it does thank you! although i have created a provider as Eduard has given really good resources to finally begin getting my head around the AngularJS architecture. – AndrewMcLagan Jul 05 '13 at 12:58
  • Useful link: http://twofuckingdevelopers.com/2014/06/angularjs-best-practices-001-constants/ – Wtower Sep 17 '16 at 18:27
2

This discussion helped me when I was trying to figure out the same thing, basically

$routeProvider.when('/', {
                templateUrl:'views/main.html',
                controller:'MainController',
                resolve: {
                    recentPosts: ['$q', 'backendService', function($q, backendService){
                        var deferred = $q.defer();
                        backendService.getRecentPosts().then(
                            function(data) {
                                var result = data.result;
                                deferred.resolve(result);
                            },
                            function(error) {
                                deferred.reject(error);
                            }
                        );
                        return deferred.promise;
                    }]
                }
            })
Vishal Seth
  • 4,948
  • 7
  • 26
  • 28