writing functions in angularjs services

All we need is an easy explanation of the problem, so here it is.

i want to write a function inside a angularjs service and i want to reuse it in all my

controllers.

var mod= angular.module('myapp', ['eventFilters', 'highlight', 'event', 'dayfilter', 'Services']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
      when('/', {templateUrl: 'template.html',   controller: Ctrl}).
      when('/temp', {templateUrl: 'temp.html',   controller: tempCtrl}).
      otherwise({redirectTo: '/invalid'});
}]);
mod.service ('sharedService', function() {
function daysInMonth(month,year) {
    return new Date(year, month+1,0).getDate();
}
});

i want to use the daysInMonth function in any of my controller.
is it possible? if so could anyone explain me briefly with some examples in fiddle.

Thanks in advance

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Here is fiddle with a basic example of how you can use (inject) services in controllers.

http://jsfiddle.net/uhmNR/1/

var myApp = angular.module('myApp',[]);


//Here is the service Users with its functions and attributes
//You can inject it in any controller, service is a singleton and its data persist between controllers
myApp.factory('Users', function () {

    var userName = "John Doe";

    return {
        getUserName: function () {
             return userName;                   
        },
        setUserName: function (newName) {
            userName = newName;
        }
    }
});

//An Util service with DaysInMonth method   
myApp.factory('Util', function () {

    return {
        daysInMonth: function (month,year) {

            return new Date(year, month+1,0).getDate();
        }
    };

});   

//Here I am injecting the User service andusing its methods   
myApp.controller('MyCtrl', ['$scope', 'Users', 'Util', function ($scope, Users, Util) {

    Users.setUserName('Robin Hood');

    $scope.name = Users.getUserName();

    //Using Util.daysInMonth()
    $scope.date = Util.daysInMonth(12,2012);
}]);

Hope It helps.

Method 2

Expose the function as a service, then let the AngularJS injector do the rest. You can easily set a daysInMonth service as a static value in your module. See this in action at http://jsfiddle.net/hbulhoes/zdtnw/

var mod = angular.module('myapp', []);

// This is the declaration of the daysInMonth service. It's set as
// a value in the module, with the value being the very function
// you want to share among other services and controllers:
mod.value('daysInMonth', function(month, year) {
    return new Date(year, month+1,0).getDate();
});

// And this is an example controller that depends on the daysInMonth function.
function MyController($scope, daysInMonth){
    $scope.DaysInCurrentMonth = daysInMonth(12, 2012);
}

Method 3

If you want a function to be available to all of your controllers, you might consider defining the method on $rootScope, instead of using a service:

myApp.run(function($rootScope) {
    $rootScope.daysInMonth = function(year, month) {
        return new Date(year, month+1,0).getDate();
    }
});

Then, due to prototypal scope inheritance, all of your controllers’ scopes will have access to the method (without the need for dependency injection). You can call it in any controller like so:

function MyCtrl($scope) {
   console.log($scope.daysInMonth(12, 2012));
}​

JavaScript won’t find function daysInMonth defined on $scope, so it will look in the parent scope (in this case the root scope) for the function, and it will find it.

Method 4

You need to expose it. Wrap it in a return block:

var mod= angular.module('myapp', ['eventFilters', 'highlight', 'event', 'dayfilter', 'Services']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
  when('/', {templateUrl: 'template.html',   controller: Ctrl}).
  when('/temp', {templateUrl: 'temp.html',   controller: tempCtrl}).
  otherwise({redirectTo: '/invalid'});
}]);
mod.service ('sharedService', function() {
   return {
      daysInMonth: function(month,year) {
         return new Date(year, month+1,0).getDate();
      }
   };
});

Method 5

If you want to use the actual Angular Service (not factory, or provider), then all you have to do is the following to create something the Angular way.

mod.service ('sharedService', function() {
  function daysInMonth(month,year) {
    return new Date(year, month+1,0).getDate();
  }
});

// Would turn into 

mod.service("sharedService", function(){
  this.daysInMonth(month, year){
    return new Date(year, month + 1, 0).getDate();
  }
});

You should not RETURN from a service unless you NEED to override the default THIS object that will be created when the service is NEW’ED. In that case, you can return an Object Literal, Function Definition, Array, most Objects excluding any primitives. Just assure you ask the question “why do I need to override the default behavior?”

That’s really the entire point of a service. When you inject the SERVICE Angular will NEW the function you pass, thus returning it to you as described. In your case, the service will be exactly what you need. Angular will build the Service just once, and the new sharedService function result will be available throughout your application, but only when the service is DI’d at least once somewhere in your application. If you don’t DI it, then the service will never be created as it is lazily loaded (Factory and Service).

If you find you really want to return something, (although you CAN do it in a service), the appropriate place would be in an Angular Factory. In fact, if you DON’T return from a Factory you will get a nice little notice

ERROR: Provider ‘sharedService’ must return a value from $get factory method.

NOTE: where the $get function is the second argument of the service function definition.

mod.factory("sharedService", function(){
  function daysInMonth(month, year){
    return new Date(year, month + 1, 0).getDate();
  }

  return {
    daysInMonth: daysInMonth
  }

  // Or you could do this...
  return daysInMonth;
});

When using the Angular Factory you no longer get a NEW’ED function, which is why a return must be created.

Method 6

I think the OP meant the service is a function, like for example the $timeout function. As the default service factory makes a “service” of whatever you return, you can do this:

angular.module('myApp.myModule',[])
.factory('add',['$injectables',function($injectables) {
  return function(arg1,arg2)
  {
    //this is the function that will be called when you use this service
    return arg1 + arg2;
  }
}]);

Usage:

angular.module('myApp.Othermodule',['myApp.myModule'])
.controller('controllername',['add',function(add) {

  //controller code and somehwere
  $scope.z = add($scope.x,$scope,y);
}]);

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply