Angular Modules to the Rescue

Written by Chris Sloan

At UserTesting, we use AngularJS for most of our features and functionality. We took on the task of introducing it to our code base for any new feature work as the current base includes BackboneJS which out of the box requires more legwork. Implementing Angular seemed like a no-brainer for what it gives, especially when the need arises to share across properties via modules.

Just recently, I rewrote our screener builder functionality to not only implement a new multi-select feature requested by Product, but also to move another set of code away from Backbone. The resulting feature not only cut down on the plethora lines of code and html needed, but was easily test-driven using our Karma spec runner setup to give double assurance alongside our Capybara request specs — but, I digress on what this post is really about: modularization.

Currently, we have two main web interfaces we support, our client-facing and internal tools properties, with features that span both. The screeners feature is one such feature that spans both: clients can build and order screeners, while our customer service reps, account managers, and research teams need to be able to manage these screeners for their clients.

Initially, I wrote a directive with a couple of services and factory to handle this new feature. It was included in our Rails assets manifest for the client side and everything was good. Then, realizing that our internal tools platform was missing this dependency, dropping in the directive seemed like a no-brainer, but something didn’t sit right with me. Modularization of this made more sense as it created a separation of concerns and dependencies.

// Original module setup for the app
angular.module(myFrontFacingApp, [DEPENDENCIES]);

// New module setup for both apps
angular.module(ScreenerModule);
angular.module(myFrontFacingApp, [ScreenerModule, DEPENDENCIES]);
angular.module(myFrontFacingApp, [ScreenerModule, DEPENDENCIES]);

Knowing I had written the initial Karma tests to live on the client side, I was a little worried about transforming the them to handle the modularization, but it turns out it was simpler than I thought. Karma dependency injection made things super simple. All I really needed to do to adjust the test was change the module I was testing and remove dependencies that it no longer needed — I have a route-ish type service for the client side utilizing Restangular; now just using the basic $http injection. Firing up the tests with those little changes, all passed and the module now worked on both properties.

Angular modules may seem daunting at first (How do I include them? How do I test them? Is the setup different? etc.), but once you grasp their power and ease of use, sharing or even open sourcing them seems like a no-brainer.