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?

2
  • Have you considered using yeoman: yeoman.io Commented Aug 11, 2013 at 10:50
  • 2
    The project was generated using yeoman. Not quite sure how it helps in this case though Commented Aug 11, 2013 at 12:36

5 Answers 5

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"
        } 
    };
});
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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

2 Comments

I believe this is the proper way to use module.
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?
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?

Comments

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

}]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.