HTML5 Zone is brought to you in partnership with:

Doug has been engrossed in programming since his parents first bought him an Apple IIe computer in 4th grade. Throughout his early career, Doug proved his flexibility and ingenuity in crafting solutions in a variety of environments. Doug’s most recent work has been in the telecom industry developing tools to analyze large amounts of network traffic using C++ and Python. Doug loves learning and synthesizing this knowledge into code and blog articles. Doug is a DZone MVB and is not an employee of DZone and has posted 36 posts at DZone. You can read more from them at their website. View Full User Profile

How to Create a Prototype Angular UI without a Back-end

09.23.2013
| 6948 views |
  • submit to reddit

So, you’ve got an AngularJS UI built out, but you’ll need a fleshed-out back-end before being able to really take it for a test drive, right? Actually, with the magic of Angular and its mocked $httpBackend, we don’t need no stinking back-end!

If you’ve heard of $httpBackend, you’ve probably heard of it it terms of writing unit tests. The tests look like this:

 // tell http backend what to do when in gets a GET request at a specific URL
    $httpBackend.when(“GET”, “/users/4”).respond( {userName: “Doug”, userId: 4} );
    // Code we’re testing
    userService.getUserById(4);
    // flush all pending requests (pretend the server just got back with response)
    $httpBackend.flush();
    expect(userService.getUser(4)).toBe( {userName: “Doug”, userId: 4});

While unit testing like this can help test and play with bits of code, it can’t drive an overall vision the way that seeing, clicking and typing into a prototype can. Therefore, I’ve taken $httpBackend and implemented a complete mock-up of my backend to allow me to use my UI and iterate quickly. Basically, I can now simply open file://path/to/my/project/index.html in my browser to use my application as if it were backed by a database on a server. That is, as long as I don’t fully reload the page. :)

How have I done this? Read along with the corresponding jsFiddle.

First, I tell Angular to use the angular-mocks $httpBackend (by passing it the $httpBackend constructor function) as a decorator on top of the concrete $httpBackend service. In Angular’s dependency injection, a decorator wraps the original service, layering on some custom functionality. In this case, Angular’s mock $httpBackend is set up to receive the concrete $httpBackend service, and will pass through to it if you use the passThrough() function after creating a rule (examples further down). In other words, I reserve the ability to pass along some requests as real HTTP requests.

 myApp
   .config(function($provide) { 
      $provide.decorator('$httpBackend', createHttpBackendMock); 
   });

All of our code to mock the backend will take place in this function, which we execute before running the angular application:

myApp.run(function($httpBackend, $timeout) {
            … <the cool stuff you’ll see below>
        });

In this run function, I can use the mock $httpBackend API to specify some rules, with actions to perform on the receipt of HTTP requests:

 // Some state
    var users = {};
    var userId = 0;
    $httpBackend.when('PUT', '/users')
    .respond(function(method, url, data) {
      data = angular.fromJson(data);
      users[userId] = {userName: data.userName, userId: userId};
      userId++;
      return [200, users[data.userId]];
    });

I can then specify some rules based on a regex, if need be:

   var regexpUrl = function(regexp) {
      return {
        test: function(url) {
          this.matches = url.match(regexp);
          return this.matches && this.matches.length > 0;
        }
      };
    };

    $httpBackend.when('GET', regexpUrl(/users\/(\d+)/))
    .respond(function(method, url, data) {
      data = angular.fromJson(data);
      return [200, users[data.userId]];
    });

And because I’m using a delegate, I can decide that certain requests will just get passed through to do real requests (say, JSONP requests to Solr from my instant search directive!):

$httpBackend.when('JSONP', regexpUrl(/http:\/\/.*/))
      .passThrough();

$httpBackend’s way of simulating an asynchronous response is for you to call flush() from your tests. So, none of our app’s requests will be responded to until we tell $httpBackend to flush. To create a kind-of $flush run-loop, we’ll use the angular $timeout service to call flush every half-second. $httpBackend still wants to be used in a unit-testing context, so it will throw an exception if there’s nothing to flush. So, we catch and discard that exception.

   var flushBackend = function() {
      try {
        $httpBackend.flush();
      } catch (err) {
      // ignore that there's nothing to flush
      }
      $timeout(flushBackend, 500 /*ms*/);
   };
   $timeout(flushBackend, 500);

Voila, now I can experiment with my UI much more efficiently! Compared to other solutions, like mocking individual angular services or creating a mockable backend service that wraps the $http calls, I have found this solution to be the cleanest and least imposing on my production code.

Have you had to solve a similar problem? Please comment and let me know! Also, do you need help with rich search- and discovery-oriented user interfaces? Let us know. We know quite a bit about building rich UIs for Solr!

Published at DZone with permission of Doug Turnbull, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)