Separate service from controller in Angularjs

Issue

I would like to separate the service from the controller in my angularjs application, I did it in a following way:

the app.js there is:

var myApp = angular.module('myApp',['restangular','ui.router','myApp.controllers','myApp.services']);

the controllers.js:

 angular.module('myApp.controllers',[]);

the services.js:

angular.module('myApp.services',[]);

I have a controllers related to the controllers.js:

angular.module('myApp.controllers',[]).controller('ContactController', ContactController);

ContactController.$inject = [ '$scope', 'ContactService' ];
function ContactController($scope, ContactService) {
     console.log("here call ctrl contact");
     $scope.contacts = ContactService.getAll(); 
}

This ContactController call the service ContactService defined in a separate file:
ContactService .js

angular.module('myApp.services',[])

.factory('ContactService', function(Restangular){
    var Contacts = Restangular.all('contacts');

    return {
        getAll : function(){
            return Contacts.getList().$object;
        }
    };

});

the problem is when I have tried to invoke this controller I got the following error:

Error: [$injector:unpr] Unknown provider: ContactServiceProvider <-
ContactService
http://errors.angularjs.org/1.2.19/$injector/unpr?p0=ContactServiceProvider%20%3C-%20ContactService

how can I fix that?

UPDATE:
this is the structure of my app:

structure of the app

I have in app.js:

.state('contacts', {
        url: '/contacts',
        templateUrl: 'templates/contacts.html',
        controller: 'ContactController'
    })  
    .state('todos', {
        url: '/todos',
        templateUrl: 'templates/todos.html',
        controller: 'TodoController'
    })

in the index.html i imported all th js files:

enter image description here

Solution

Once you have initialized a module withm, angular.module('myApp.controllers', []) again you should not use second parameter dependency([])

So,
in your controller,

 `angular.module('myApp.controllers',[])` should be `angular.module('myApp.controllers')`

So,

angular
  .module('myApp.controllers')
  .controller('ContactController', ContactController);
ContactController.$inject = ['$scope', 'ContactService'];
function ContactController($scope, ContactService) {
  console.log('here call ctrl contact');
  $scope.contacts = ContactService.getAll();
}

The same applies to your service/factory,

angular.module('myApp.services')
.factory('ContactService', function(Restangular){
    var Contacts = Restangular.all('contacts');

    return {
        getAll : function(){
            return Contacts.getList().$object;
        }
    };

});

PS: After seeing the order of your js file injection in index.html I found the major issue.

The order of your file scripts is wrong. In ContactController you are using contactService which is not defined before it.
So change the scripts order in index.html as below.

<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/services/ContactService.js"></script>
<script src="js/services/TodoService.js"></script>
<script src="js/controllers/HomeController.js"></script>
<script src="js/controllers/ContactController.js"></script>
<script src="js/controllers/TodoController.js"></script>

Answered By – Sravan

Answer Checked By – Willingham (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.