angular.js - best practice for defining a utility library
Asked Answered
K

3

10

I'm giving my first steps with angular, and I need to define a utility helper library, with a couple of function methods, something like

dataHelper.parse, dataHelper.sanitize, etc

What would be the recommended way to organize it in angular?

Ken answered 7/7, 2014 at 6:19 Comment(0)
G
16

For utility methods, I would organize them in a library outside of the Angular framework, but with a small dependency on angular.extend. If you want your library completely independent of Angular, you can substitute extend with your own implementation.

Wrap your utility API in a JavaScript enclosure and expose your library as a property of window (in the example below, I've named my library myLibrary, but you're free to choose whichever name you like). By attaching your library as a property of window, you will be able to reference 'myLibrary' without qualification. If you are curious, this is exactly how the angular library is exposed.

 (function (window, document) {
     'use strict';

     // attach myLibrary as a property of window
     var myLibrary = window.myLibrary || (window.myLibrary = {});

     // BEGIN API
     function helloWorld() {
         alert('hello world!');
     }

     function utilityMethod1() {
         alert('Utility Method 1');
     }

     function utilityMethod2() {
         alert('Utility Method 2');
     }
     // END API

     // publish external API by extending myLibrary
     function publishExternalAPI(myLibrary) {
         angular.extend(myLibrary, {
             'helloWorld': helloWorld,
             'utilityMethod1': utilityMethod1,
             'utilityMethod2': utilityMethod2
         });
     }


     publishExternalAPI(myLibrary);

 })(window, document);

Usage

Once the script is added, you can use your library from anywhere - services, factories, providers, controllers, directives etc.

<script type='text/javascript' src='angular.js'></script>
<script type='text/javascript' src='myLibrary.js'></script>

<script>
      myLibrary.helloWorld();
      myLibrary.utilityMethod1();
      myLibrary.utilityMethod2();
</script>

Utility Library vs Angular Services

The reason that I prefer utility functions to reside in their own library rather than in angular services is because I think of them as being separate from the angular ecosystem. These utility functions are pretty much stand-alone and are module agnostic, while angular services/factories work closely with other parts of angular, including controllers and directives, and are very much closely tied to the module.

Extending Angular

If you really wanted, you could even extend the angular library itself. Just substitute myLibrary with angular in the script (Note: this may not be advisable as it would make your scripts dependent on the Angular implementation).

Gaillard answered 7/7, 2014 at 7:28 Comment(3)
This is indeed a pretty good idea. Is there any way of using an Angular service in external code?Bombazine
There is, but you would need to use angular's $injector: var $injector = angular.injector(); var myService = $injector.get('myService');Gaillard
I am having trouble returning a value from the API functions. I've confirmed that the API function is called but from the caller, the return value is undefined. Do I miss anything?Excellency
B
0

Create a custom service

globalModule.service('toolkit',function(){

return{
   
    getDate: function(altFormat){
        var today = new Date();
        var dd = today.getDate();
        var mm = today.getMonth()+1; //January is 0!

        var yyyy = today.getFullYear();
        if(dd<10){dd='0'+dd} if(mm<10){mm='0'+mm} today = yyyy +'-'+ mm+'-'+dd;

        if(altFormat){
            today = today.replace(/-/g, '.');
        }

        return today;
    },

    /**
     *  Returns a 32 character ID [ XXXXXXXX - XXXXXXXXXXXXXXXXXXXXXXXX ]
     * @returns {string}
     */

    newGUID: function(){

        // ...
    }

  };
});

You can inject it wherever it is needed. If you can bundle some logic into seperate services (e.g parseService) I think you should do so.

If you need something more flexible or configurable, have a look at providers.

Bombazine answered 7/7, 2014 at 6:25 Comment(2)
This was downvoted. I'd be happy to hear about any suggestions the downvoter would make to improve this answer.Bombazine
the one downside of this is you can't use it in a config block.Oddfellow
K
0

To extend @pixelbits' answer, if you'd like to keep your external dependencies explicit, you can fairly easily wrap existing libraries for use with Angular, like this for momentjs:

angular.module('testApp')
.constant( 'moment', moment)
Knecht answered 8/10, 2016 at 0:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.