akkonrad
akkonrad

Reputation: 1073

Injecting custom service into ui-router config throws error: Unknown provider: [Service]

I would like to inject my custom service into angular app in ui-router config function. So I'm defining router as below, but when trying to $inject service I get error: Unknown provider: Auth. Here is code sample:

 'use strict';

  angular.module('app.project').config(config);

  // This throws error Unknown provider: Auth
  // config.$inject = ['$stateProvider', 'Auth'];

  // This works, but Auth is of course undefined.
  config.$inject = ['$stateProvider'];

  function config($stateProvider, Auth) {
     console.log(Auth);

     $stateProvider.state('default', {
       url: '/',
       template: `<div>default page. </div>
                  <a ui-sref="default">default</a><br>
                  <a ui-sref="projects">projects</a>`,
       data: {
         authorizedRoles: ['admin', 'editor']
       }
     });

  }

Here is working examlpe of the app on plunker: https://embed.plnkr.co/yIGMLCdOIHsB945NsHDl/

I think I'm injecting that in correct way. Changing code to use "iife" won't change anything (I've checked that already).

Upvotes: 2

Views: 2503

Answers (2)

georgeawg
georgeawg

Reputation: 48968

Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.1

Services can only be injected during the AngularJS run phase, or in resolver functions:

Code

//function config($stateProvider, Auth) {
function config($stateProvider) {
     $stateProvider.state('default', {
         url: '/',
         template: '<div>default page.'+
                    '<a ui-sref="default">default</a><br>'+
                    '<a ui-sref="projects">projects</a>'+
                  '</div>',
         data: {
             authorizedRoles: ['admin', 'editor']
         },
         //INJECT services in resolve functions
         resolve: {
             role: ["Auth", "$q", function(Auth, $q) {
                 return Auth.getUser().then(function(user) {
                     return user.role;
                 }).catch(function(error) {
                     return $q.reject(error);
                 });
            }]
         }
     });
}

Because resolver functions are stored and only invoked when the state attempts to load, it is possible to inject services at that time.

Upvotes: 2

Stefan Zurfluh
Stefan Zurfluh

Reputation: 46

According to https://docs.angularjs.org/guide/module:

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.

In order to be able to inject a service to a configuration, it needs to be written using the provider pattern:

angular.module('app.main')
  .service('AuthProvider', function AuthProvider() {
    this.$get = ['$http', function factory($http) {
      return new AuthService($http);
    }];
  });

function AuthService($http) {

(...)

Upvotes: 3

Related Questions