5

I am trying to reduce code repetition with my directives. I would like to write a helper function that generates the directives instead of defining them manually. Changing the directive definition to something like:

mydirectiveBuilder(function myButton(){
  return {
    scope: {
      toggle: "@pressed"
    }
  };
});

I am not sure where this should go (other then hanging it off window). Does angular provide a place for these sorts of methods to go?

gingermusketeer
  • 618
  • 1
  • 6
  • 6

5 Answers5

5

Angular doesn't provide anything, but uses angular as a namespace for its own helper functions. You could simply do the same:

var myApp = (function() {
    // private function, not visible from the outside
    function privateFunction() {
        ...
    }

    function mydirectiveBuilder() {
       ...
       // you can use privateFunction here
    }

    return {
        mydirectiveBuilder: mydirectiveBuilder;
    };
})();

And in your directives:

myApp.mydirectiveBuilder(function myButton(){
    return {
        scope: {
            toggle: "@pressed"
        } 
    };
});
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
5

You could either do what @JB Nizet suggests or if you don't like the idea of exposing something like myApp to the global scope, you just put the function somewhere and then wrap everything in a closure as a build step.

File: directiveHelpers.js

function myDirectiveBuilder(){
}

File: someDirective.js

myDirectiveBuilder(function myButton(){
    return {
        scope: {
            toggle: "@pressed"
        } 
    };
});

Then as a build step you concat all files and as a final build step you put a closure around it so it essentially becomes:

File: app.js

(function(){

    function myDirectiveBuilder(){
    }

    myDirectiveBuilder(function myButton(){
        return {
            scope: {
                toggle: "@pressed"
            } 
        };
    });
})();

This technique is used by Angular itself throughout the code base.

Christoph
  • 26,519
  • 28
  • 95
  • 133
4

Another way to go about this is to attach say a UTIL object containing your helper functions to the root scope. This is captured in this tutorial

angular.module("app", ["ngResource", "ngRoute"]).run(function($rootScope) {

  //app util functions
  $rootScope.UTIL = {

  toFilename: function(filename) {
    return filename
      .toLowerCase()
      .replace(/ /g,'-')
      .replace(/[^\w-]+/g,'');
  },

  fromFilename: function(filename) {
    return filename
      .toLowerCase()
      .replace(/[^\w ]+/g,'')
      .replace(/ +/g,'-');
  }

  //etc more functions here...

 };

}

And then you can call the helper functions like;

$scope.UTIL.toFilename( filename );
$scope.UTIL.fromFilename( filename );
etc...

Snippets credit to the AngularJS4U post (link above).

dantheta
  • 1,107
  • 2
  • 13
  • 29
  • I believe this is the proper way to use module. – KimchiMan Nov 29 '14 at 05:08
  • 1
    This worked for me really well in controllers/services/directives. But is there a way to have this UTIL object injected in initialisation stage - so that I could use it in providers? – shershen Feb 19 '15 at 16:23
2

I'm against putting these utils in global scope, which is a very bad practice. One option I found reasonable is to use service to declare these utils and then use inject them as dependencies as needed. This is similar to import libraries as need without polluting global scope.

angular.
  module('phonecatApp').
  factory('strHelpers', [
    function () {
      return {
        snippingStr: function(str) {
          return str.substring(1,20) + "...";
        }
      }
  }])

Usage:

function usage(strHelpers) {
  console.info("Demonstrating console.log and helper function: " +
    strHelpers.snippingStr("111111111122222222223333333333"));
}

This is suggested by Matt Way here: Where is a good place to put a few small utility functions in AngularJS?

Community
  • 1
  • 1
oVo
  • 111
  • 1
  • 3
0

Here is a simple, compact and easy to understand method I use.
First, add a service in your js that will be dedicated to receive your helper functions.

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);

}]);