Wednesday, April 9, 2014

Exposing global libraries as module constants in angularjs

I want to use the awesome underscore library with angular.  Although you can just drop the library in your html file and reference the _ variable as a global, I wanted to pass it into my app's module with angular's dependency injection.  The main advantages here are:

1. Explicit definition of dependencies

Having the objects/services/controller/etc that something depends on defined makes it easier to re-use components elsewhere.  This helps avoid the annoying '_' is not defined type of errors, but also helps prevent some more subtle bugs if you are depending on a undefined global in a part of your code that doesn't get run very often.

2. Testability

If we inject underscore, we could mock it out or wrap it during a test.  This would allow us to do cool things like see how many times a certain underscore function was called.

How do you do this?  At first I read this article that discussed wrapping it in a factory.  This certainly works, but since angular has the nice interface for defining inject-able constants, I used that instead.  So all the code you need is:

var app = angular.module('MyApp');
app.constant('_', window._ );


Yep.  That's it.  And the first line is just to give you context.

To use this in a controller, do something like this:

app.service('MyService', ['_', function(_){
  // Your code goes here
}])


Pretty simple.

2 comments: