4

I need some help out there. I am learning Angularjs and trying to create a service. Currently I am trying to separate everything in their modules. When I create a new module called (bac.route-manager) and try to inject it in the app config as RouterService I get an error that I do not understand the meaning or how to fix it. All my other stuff seems to work, except when I tried to add this module this unknown provider starts showing up only after I try to inject it. Please any help is appreciated.

My error

Uncaught Error: Unknown provider: RouterService from bac

My app.js file

angular.module('bac', [
   'bac.route-manager'
])

.config( function bacAppConfig( $routeProvider, RouterService ) {

     //I dont knwo if i can do this but right now it doesnt matter because of error
     console.log(RouterService.getRoutes());
});

My route-manager.js file

angular.module('bac.route-manager', [])

.service('RouterService', function() {

    this.getRoutes = function() {
        return {
                "/login": {
            templateUrl: 'app/modules/login-manager/partials/login.tpl.html',
             requiredLogin: false
         },

        "/dashboard": {
            templateUrl: 'app/modules/dashboard-manager/partials/dashboard.tpl.html',
            controller: 'DashboardController',
            requiredLogin: true
         }

        };

};

});

I using grunt to generate the js includes in my html file but here is what that looks like with alot of stuff removed for brevity.

My index.html

<html lang="en" class="no-js" ng-app="bac">
    <body>
        <ng-view></ng-view>

     <script type="text/javascript" src="vendor/angular/angular.js"></script>
     <script type="text/javascript" src="app/app.js"></script>
     <script type="text/javascript" src="app/modules/dashboard-manager/dashboard-manager.js"></script>
     <script type="text/javascript" src="app/modules/route-manager/route-manager.js"></script>

    </body>
</html>
lumberjacked
  • 966
  • 1
  • 21
  • 35
  • Try loading `route-manager.js` before `app.js` – AlwaysALearner Aug 16 '13 at 14:55
  • I just tried that. I generated the index.html file with grunt and then went in and manually moved the route-manager.js file above everything except the app.js file. Still same error. Uncaught Error: Unknown provider: RouterService from bac – lumberjacked Aug 16 '13 at 14:58
  • @Codezilla The config and run phase is deferred until the whole document is loaded. The order in which they appear is irrelevant in this case. – Simon Belanger Aug 16 '13 at 15:03
  • http://stackoverflow.com/questions/15244272/angularjs-error-unknown-provider – START RUN CMD Aug 16 '13 at 15:04
  • @STARTRUNCMD Not a duplicate of that question since the `bac` module already define `bac.route-manager` as a dependency. – Simon Belanger Aug 16 '13 at 15:08

1 Answers1

17

In the config phase, the services declared are not available yet. Only those who have been declared using provide will through serviceNameProvider (add Provider after the name you have defined). For example:

.provide('RouterService', function() {
  var service = { };
  var routes = {
    "/login": {
      templateUrl: 'app/modules/login-manager/partials/login.tpl.html',
      requiredLogin: false
    }, 
    "/dashboard": {
        templateUrl: 'app/modules/dashboard-manager/partials/dashboard.tpl.html',
        controller: 'DashboardController',
        requiredLogin: true
     }};

  service.getRoutes = function() { return routes; };

  this.$get = function() { return service; }

  this.setupRoute = function(data) { /* something here */ };
};

When you get a provider, all method defined on this will be available. When you access the normal service, what is injected is the return of the $get function. Depending on what you need, you either need to change your service to use provide or ask to be injected with the service in the run method:

angular.module('bac', ['bac.route-manager'])
  .config(function ($routeProvider, RouterServiceProvider) {
    // Here, only RouterServiceProvider.setupRoute will be available
  }).run(function (RouterService) {
    // Here, the service singleton return with the $get function will
    // be injected
    console.log(RouterService.getRoutes());
});

Edit

As a side note, I believe that even if you have defined your RouterService as a service, asking for RouterServiceProvider would still work but no method will be present as service is essentially a wrapper around provider to only return the function in the $get

Simon Belanger
  • 14,752
  • 3
  • 41
  • 35
  • Thanks for the response. I'm going to re-factor and then I'll mark this as the answer. – lumberjacked Aug 16 '13 at 15:20
  • Converting the service to a provider works. But I'm confused at how to implement the $get method. Inside the provider I added a this.getRoutes() method so that I could next loop through the object to configure the routes in $routeProvider. I don't really need a $get method at this stage, maybe later, but can't I just inject the RouterServiceProvider in a controller to use the this.getRoutes() method. – lumberjacked Aug 16 '13 at 16:18