Rectangle 27 1

angularjs Inject service in app.config?


$httpProvider.interceptors.push(function($injector) {
    return {
        "responseError": function(response) {

            console.log("Error Response status: " + response.status);

            if (response.status === 0) {
                var myService= $injector.get("myService");
                myService.showError("An unexpected error occurred. Please refresh the page.")
            }
        }
    }

Using $injector to call service methods in config

I had a similar issue and resolved it by using the $injector service as shown above. I tried injecting the service directly but ended up with a circular dependency on $http. The service displays a modal with the error and I am using ui-bootstrap modal which also has a dependency on $https.

Note
Rectangle 27 1

angularjs Inject service in app.config?


resolve: {
  data: function (dbService) {
    return dbService.getData();
  }
}

@BrianVanderbusch I must to admit to some confusion over where exactly you feel we disagree. The actual problem the OP encountered was that he injected a service into a config block, which cannot be done. The solution is to inject the service into the resolve. While your answer provided a lot of detail about service configuration, I do not see how it related in any way to the error the OP encountered, and your solution to the OP's problem was exactly the same: you injected the service in the resolve function and not the config function. Can you elaborate on where we disagree here?

@JoshDavidMiller Using the method I demonstrated, it's possible to configure a service prior to state activation, such that errors can be thrown/handled during the config phase, potentially altering how you would instantiate other configuration values prior to application bootstrapping. For example, determining the role of a user in order to have the application compile the right features.

@XMLilley The string in a resolve is actually the name of a service and not a particular function on the service. Using your example, you could do pageData: 'myData', but you would then have to call pageData.overview from your controller. The string method is probably only useful if the service factory returned a promise instead of an API. So the way you're currently doing it is probably the best way.

Alex provided the correct reason for not being able to do what you're trying to do, so +1. But you are encountering this issue because you're not quite using resolves how they're designed.

Thanks! However, if I do this I get: Error: 'undefined' is not an object (evaluating '$q.defer') in the the service.

The injection occurs in the top-level function passed to .service, so move $q and $http there.

When the framework goes to resolve data, it will inject the dbService into the function so you can freely use it. You don't need to inject into the config block at all to accomplish this.

resolve takes either the string of a service or a function returning a value to be injected. Since you're doing the latter, you need to pass in an actual function:

Note
Rectangle 27 0

angularjs Inject service in app.config?


A module is a collection of configuration and run blocks which get applied to the application during the bootstrap process. In its simplest form the module consist of collection of two kinds of blocks:

Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.

Short answer: you can't. AngularJS won't allow you to inject services into the config because it can't be sure they have been loaded correctly.

Note
Rectangle 27 0

angularjs Inject service in app.config?


app.config(function ($routeProvider) { 


    $routeProvider
        .when('/',
        {
            templateUrl: "partials/editor.html",
            controller: "AppCtrl",
          resolve: {
              dbData: function(DbService, $http){
                 /*
                 *dbServiceProvider returns a dbService instance to your app whenever
                 * needed, and this instance is setup internally with a promise, 
                 * so you don't need to worry about $q and all that
                 */
                 return DbService('http://dbhost.com').getData();
              }
          }
        })
});
app.config(function($routeProvider, $provide){
  $provide.service('dbService',function(){})//set up your service inside the module's config.

  $routeProvider
        .when('/',
        {
            templateUrl: "partials/editor.html",
            controller: "AppCtrl",
            resolve: {
                data: 
                }
            }
        })


});
app.controller('appCtrl',function(dbData, DbService){
     $scope.dbData = dbData;

     //you can also create and use another instance of the dbService here...
     // to do whatever you programmed it to do, by adding functions inside the constructor
     // DbService(), the following assumes you added a rmUser(userObj) function in the factory
     $scope.removeDbUser = function(user){
         DbService.rmUser(user);
     }

})
app.provider('dbService', function dbServiceProvider() {

  //the provider recipe for services require you specify a $get function
  this.$get= ['dbhost',function dbServiceFactory(dbhost){

     return new DbService(dbhost);  //return the factory as a provider, that is available during the configuration phase
  }]

});

  function DbService(dbhost){
      var status;
      this.setUrl = function(url){
          dbhost = url;
      }


      this.getData = function($http){
            return $http.get(dbhost+'db.php/score/getData')
                    .success(function(data){
                        //handle any special stuff here, I would suggest the following:
                        status = 'ok';
                        status.data = data;
                     })
                     .error(function(message){
                        status = 'error';
                        status.message = message;

                     })
                     .then(function(){
                         return status;  // now we return an object with data or information about error for special handling inside your application configuration
                      })
      }
  }
appCtrl
factory
provider
service
  • John Lindquist has an excellent 5 minute explanation and demonstration of this at egghead.io, and it's one of the free lessons! I basically modified his demonstration by making it $http specific in the context of this request
  • View the AngularJS Developer guide on Providers

@Alkaline I have learned a thing or two since this post. The answer is correct in theory but has 1 or 2 things (1 you pointed out) that should be fixed. Thanks for the comment. I'll review and update the answer. Deleted the codepen for the moment... never had a chance to finish it.

Despite what the Accepted answer says, you actually CAN do what you were intending to do, but you need to set it up as a configurable provider, so that it's available as a service during the configuration phase.. First, change your Service to a provider as shown below. The key difference here is that after setting the value of defer, you set the defer.promise property to the promise object returned by $http.get:

It would really be useful if your codepen samples worked. For instance, $provide.service('dbService',function(){ doesn't have $http injected but uses it in its body. As it stands, I could not get your technique 2 to work. It's very frustrating that it is so hard to load config data from a remove file in an Angular program at startup.

Now, you have a configurable custom Provider, you just need to inject it. Key difference here being the missing "Provider on your injectable".

The following alternative is a similar approach, but allows definition to occur within the .config, encapsulating the service to within the specific module in the context of your app. Choose the method that right for you. Also see below for notes on a 3rd alternative and helpful links to help you get the hang of all these things

The provider gives you a bit more configuration over the .service method, which makes it better as an application level provider, but you could also encapsulate this within the config object itself by injecting $provide into config like so:

Note
Rectangle 27 0

angularjs Inject service in app.config?


app.config(function ($routeProvider) { 
    $routeProvider
        .when('/', {
            templateUrl: "partials/editor.html",
            controller: "AppCtrl",
            resolve: {
                dbData: function(DbService, $http) {
                     /*
                     *dbServiceProvider returns a dbService instance to your app whenever
                     * needed, and this instance is setup internally with a promise, 
                     * so you don't need to worry about $q and all that
                     */
                    return DbService('http://dbhost.com').getData();
                }
            }
        })
});
app.config(function($routeProvider, $provide) {
    $provide.service('dbService',function(){})
    //set up your service inside the module's config.

    $routeProvider
        .when('/', {
            templateUrl: "partials/editor.html",
            controller: "AppCtrl",
            resolve: {
                data: 
            }
        })
});
app.controller('appCtrl',function(dbData, DbService){
     $scope.dbData = dbData;

     // You can also create and use another instance of the dbService here...
     // to do whatever you programmed it to do, by adding functions inside the 
     // constructor DbService(), the following assumes you added 
     // a rmUser(userObj) function in the factory
     $scope.removeDbUser = function(user){
         DbService.rmUser(user);
     }

})
app.provider('dbService', function dbServiceProvider() {

  //the provider recipe for services require you specify a $get function
  this.$get= ['dbhost',function dbServiceFactory(dbhost){
     // return the factory as a provider
     // that is available during the configuration phase
     return new DbService(dbhost);  
  }]

});

function DbService(dbhost){
    var status;

    this.setUrl = function(url){
        dbhost = url;
    }

    this.getData = function($http) {
        return $http.get(dbhost+'db.php/score/getData')
            .success(function(data){
                 // handle any special stuff here, I would suggest the following:
                 status = 'ok';
                 status.data = data;
             })
             .error(function(message){
                 status = 'error';
                 status.message = message;
             })
             .then(function(){
                 // now we return an object with data or information about error 
                 // for special handling inside your application configuration
                 return status;
             })
    }    
}
appCtrl
factory
provider
service
  • John Lindquist has an excellent 5 minute explanation and demonstration of this at egghead.io, and it's one of the free lessons! I basically modified his demonstration by making it $http specific in the context of this request
  • View the AngularJS Developer guide on Providers

@Alkaline I have learned a thing or two since this post. The answer is correct in theory but has 1 or 2 things (1 you pointed out) that should be fixed. Thanks for the comment. I'll review and update the answer. Deleted the codepen for the moment... never had a chance to finish it.

Despite what the Accepted answer says, you actually CAN do what you were intending to do, but you need to set it up as a configurable provider, so that it's available as a service during the configuration phase.. First, change your Service to a provider as shown below. The key difference here is that after setting the value of defer, you set the defer.promise property to the promise object returned by $http.get:

I think the information you provided here is incorrect. You can use a provider but during config phase you're not working with the result of the $get call. Instead you want to add methods on the provider instance and just return this when you call $get. In fact in your example you could just use a service... In a provider you also can't inject services like $http. And btw this //return the factory as a provider, that is available during the configuration phase is misleading/incorrect information

It would really be useful if your codepen samples worked. For instance, $provide.service('dbService',function(){ doesn't have $http injected but uses it in its body. As it stands, I could not get your technique 2 to work. It's very frustrating that it is so hard to load config data from a remove file in an Angular program at startup.

Now, you have a configurable custom Provider, you just need to inject it. Key difference here being the missing "Provider on your injectable".

The following alternative is a similar approach, but allows definition to occur within the .config, encapsulating the service to within the specific module in the context of your app. Choose the method that right for you. Also see below for notes on a 3rd alternative and helpful links to help you get the hang of all these things

The provider gives you a bit more configuration over the .service method, which makes it better as an application level provider, but you could also encapsulate this within the config object itself by injecting $provide into config like so:

Note
Rectangle 27 0

angularjs Inject service in app.config?


A module is a collection of configuration and run blocks which get applied to the application during the bootstrap process. In its simplest form the module consist of collection of two kinds of blocks:

Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.

Short answer: you can't. AngularJS won't allow you to inject services into the config because it can't be sure they have been loaded correctly.

Note
Rectangle 27 0

angularjs Inject service in app.config?


var base = angular.module('myAppBaseModule', [])
base.factory('Foo', function() { 
  console.log("Foo");
  var Foo = function(name) { this.name = name; };
  Foo.prototype.hello = function() {
    return "Hello from factory instance " + this.name;
  }
  return Foo;
})
base.service('serviceFoo', function() {
  this.hello = function() {
    return "Service says hello";
  }
  return this;
});

var app = angular.module('appModule', []);
app.config(function($provide) {
  var base = angular.injector(['myAppBaseModule']);
  $provide.constant('Foo', base.get('Foo'));
  $provide.constant('serviceFoo', base.get('serviceFoo'));
});
app.controller('appCtrl', function($scope, Foo, serviceFoo) {
  $scope.appHello = (new Foo("app")).hello();
  $scope.serviceHello = serviceFoo.hello();
});

Explicitly request services from other modules using anuglar.injector

Here's a more explicit, and probably more reliable way to do it + a working plunker

However, I'm not sure if the *Provider (which is made internally by angular after it processes a service, or factory) will always be available (it may depend on what else loaded first), as angular lazily loads modules.

Just to elaborate on kim3er's answer, you can provide services, factories, etc without changing them to providers, as long as they are included in other modules.

Note that if you want to re-inject the values that they should be treated as constants

Note
Rectangle 27 0

angularjs Inject service in app.config?


You can use $inject service to inject a service in you config

Note
Rectangle 27 0

angularjs Inject service in app.config?


angular.module('dogmaService', [])
    .factory('dogmaCacheBuster', [
        function() {
            return function(path) {
                return path + '?_=' + Date.now();
            };
        }
    ]);

angular.module('touch', [
        'dogmaForm',
        'dogmaValidate',
        'dogmaPresentation',
        'dogmaController',
        'dogmaService',
    ])
    .config([
        '$routeProvider',
        'dogmaCacheBusterProvider',
        function($routeProvider, cacheBuster) {
            var bust = cacheBuster.$get[0]();

            $routeProvider
                .when('/', {
                    templateUrl: bust('touch/customer'),
                    controller: 'CustomerCtrl'
                })
                .when('/screen2', {
                    templateUrl: bust('touch/screen2'),
                    controller: 'Screen2Ctrl'
                })
                .otherwise({
                    redirectTo: bust('/')
                });
        }
    ]);

angular.module('dogmaController', [])
    .controller('CustomerCtrl', [
        '$scope',
        '$http',
        '$location',
        'dogmaCacheBuster',
        function($scope, $http, $location, cacheBuster) {

            $scope.submit = function() {
                $.ajax({
                    url: cacheBuster('/customers'),  //server script to process data
                    type: 'POST',
                    //Ajax events
                    // Form data
                    data: formData,
                    //Options to tell JQuery not to process data or worry about content-type
                    cache: false,
                    contentType: false,
                    processData: false,
                    success: function() {
                        $location
                            .path('/screen2');

                        $scope.$$phase || $scope.$apply();
                    }
                });
            };
        }
    ]);

@pro.mean I think I was demonstrating the technique I used, to insert a service into a config block, but it has been a while. cacheBuster is defined, as a parameter of the config function. With regards to dogmaCacheBusterProvider, it's something clever that Angular does with naming conventions, that I have long since forgotten. This might get you closer, stackoverflow.com/a/20881705/110010.

I don't think you're supposed to be able to do this, but I have successfully injected a service into a config block. (AngularJS v1.0.7)

on this another reference. I come to know that append Provider whatever we define in .provider() recipe. what if I define something with .factory('ServiceName') or .service('ServiceName') recipe and want to use one of its method in .config block , set the parameter as ServiceNameProvider but it stops my application.

service method name is dogmaCacheBuster but in .config you have written cacheBuster ( which is not defined anywhere in the answer) and dogmaCacheBusterProvider ( which is not used further). Will you clarify over this?

Note