[angularjs] How can I add some small utility functions to my AngularJS application?

I would like to add some utility functions to my AngularJS application. For example:

$scope.isNotString = function (str) {
    return (typeof str !== "string");
}

Is the best way to do this to add them as a service? From what I have read I can do this but then I would like to use these in my HTML pages so is it still possible if they are in a service? For example can I use the following:

 <button data-ng-click="doSomething()"
         data-ng-disabled="isNotString(abc)">Do Something
 </button>

Can someone give me an example of how I could add these. Should I create a service or is there some other way of doing it. Most important I would like these utility functions in a file and not combined with another part of the main set up.

I understand there's a few solutions but none of them are so clear.

Solution 1 - Proposed by Urban

$scope.doSomething = ServiceName.functionName;

The problem here is I have 20 functions and ten controllers. If I did this it would mean adding a lot of code to each controller.

Solution 2 - Proposed by me

    var factory = {

        Setup: function ($scope) {

            $scope.isNotString = function (str) {
                return (typeof str !== "string");
            }

The disadvantage of this is that at the start of every controller I would have one or more of these Setup calls to each service which passed the $scope.

Solution 3 - Proposed by Urban

The solution proposed by urban of creating a generic service looks good. Here's my main set up:

var app = angular
    .module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
    .config(['$locationProvider', '$sceProvider', '$stateProvider',
        function ($locationProvider, $sceProvider, $stateProvider) {

            $sceProvider.enabled(false);
            $locationProvider.html5Mode(true);

Should I add the generic service to this and how could I do it ?

This question is related to angularjs

The answer is


Here is a simple, compact and easy to understand method I use.
First, add a service in your js.

app.factory('Helpers', [ function() {
      // Helper service body

        var o = {
        Helpers: []

        };

        // Dummy function with parameter being passed
        o.getFooBar = function(para) {

            var valueIneed = para + " " + "World!";

            return valueIneed;

          };

        // Other helper functions can be added here ...

        // And we return the helper object ...
        return o;

    }]);

Then, in your controller, inject your helper object and use any available function with something like the following:

app.controller('MainCtrl', [

'$scope',
'Helpers',

function($scope, Helpers){

    $scope.sayIt = Helpers.getFooBar("Hello");
    console.log($scope.sayIt);

}]);

Do I understand correctly that you just want to define some utility methods and make them available in templates?

You don't have to add them to every controller. Just define a single controller for all the utility methods and attach that controller to <html> or <body> (using the ngController directive). Any other controllers you attach anywhere under <html> (meaning anywhere, period) or <body> (anywhere but <head>) will inherit that $scope and will have access to those methods.


Coming on this old thread i wanted to stress that

1°) utility functions may (should?) be added to the rootscope via module.run. There is no need to instanciate a specific root level controller for this purpose.

angular.module('myApp').run(function($rootScope){
  $rootScope.isNotString = function(str) {
   return (typeof str !== "string");
  }
});

2°) If you organize your code into separate modules you should use angular services or factory and then inject them into the function passed to the run block, as follow:

angular.module('myApp').factory('myHelperMethods', function(){
  return {
    isNotString: function(str) {
      return (typeof str !== 'string');
    }
  }
});

angular.module('myApp').run(function($rootScope, myHelperMethods){ 
  $rootScope.helpers = myHelperMethods;
});

3°) My understanding is that in views, for most of the cases you need these helper functions to apply some kind of formatting to strings you display. What you need in this last case is to use angular filters

And if you have structured some low level helper methods into angular services or factory, just inject them within your filter constructor :

angular.module('myApp').filter('myFilter', function(myHelperMethods){ 
  return function(aString){
    if (myHelperMethods.isNotString(aString)){
      return 
    }
    else{
      // something else 
    }
  }
);

And in your view :

{{ aString | myFilter }}   

You can also use the constant service as such. Defining the function outside of the constant call allows it to be recursive as well.

function doSomething( a, b ) {
    return a + b;
};

angular.module('moduleName',[])
    // Define
    .constant('$doSomething', doSomething)
    // Usage
    .controller( 'SomeController', function( $doSomething ) {
        $scope.added = $doSomething( 100, 200 );
    })
;

Why not use controller inheritance, all methods/properties defined in scope of HeaderCtrl are accessible in the controller inside ng-view. $scope.servHelper is accessible in all your controllers.

    angular.module('fnetApp').controller('HeaderCtrl', function ($scope, MyHelperService) {
      $scope.servHelper = MyHelperService;
    });


<div ng-controller="HeaderCtrl">
  <div ng-view=""></div>
</div>

The easiest way to add utility functions is to leave them at the global level:

function myUtilityFunction(x) { return "do something with "+x; }

Then, the simplest way to add a utility function (to a controller) is to assign it to $scope, like this:

$scope.doSomething = myUtilityFunction;

Then you can call it like this:

{{ doSomething(x) }}

or like this:

ng-click="doSomething(x)"

EDIT:

The original question is if the best way to add a utility function is through a service. I say no, if the function is simple enough (like the isNotString() example provided by the OP).

The benefit of writing a service is to replace it with another (via injection) for the purpose of testing. Taken to an extreme, do you need to inject every single utility function into your controller?

The documentation says to simply define behavior in the controller (like $scope.double): http://docs.angularjs.org/guide/controller