Single Page Apps with Node and Angular

Single-page JavaScript web apps seem to be all the rage right now. I don’t think I’ve gone more than a day or two without seeing another blog debating the merits of Backbone, Knockout, Ember, Angular, and the myriad other client-side frameworks.

For me, it started with jQuery Mobile. This was my first taste of paging within a single DOM, requesting only data from the server. Unfortunately, jQuery Mobile isn’t something that is meant to be used on all devices from mobile to desktop.

This is where responsive design with media queries comes into play. In some ways responsive design is like coming up with several different fixed-width layouts, but it’s more sophisticated than that. Media queries target width-based “break-points” and add css which overrides the default styles. Clever use of these techniques can produce a website which looks decent on everything from mobile sized screens to large desktops.

So where have I ended up? Here’s a top-down look at the way my single page app works.

Server Side

The server, based off the angular-express-seed, is Node and Express, and has only two essential functions. The first is to serve static files. A directory public contains all css, images, and javascripts. Another views directory contains Jade templates. The angular-express-seed project is not designed specifically with single page apps in mind, so by default the views folder contains a subfolder for partials that contain any widgets or small pages you might need, but I really only rely on the index file containing everything.

So beyond static files, the only other thing the server does is provide a json api for all the core data operations of the app. The main file for the app lists all possible routes. I list out all my api URIs first, and then lastly default to serving the index html.


var express = require('express'),
    routes = require('./routes'),
    api = require('./routes/api');

var app = module.exports = express.createServer();

app.configure(function() {
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.set('view options', {
        layout: false,
        pretty: true
    app.use(express.static(__dirname + '/public'));

//RESTful Routes
app.get('/api/posts', api.posts);
app.get('/api/post/:post_id',;'/api/posts', api.postAdd);
app.put('/api/post/:post_id', api.postEdit);
app.delete('/api/post/:post_id', api.postDelete);

app.get('*', routes.index);

app.listen(3000, function() {
    console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

Client Side

The client is all about Angular.js. It starts with an app module definition and some predefined routes. This took a minute to wrap my brain around, since we’re basically routing on the client and the server. But it really makes a lot of sense. The client and api routes follow similar patterns, but they must be different. This is why the api routes all start with the prefix “/api” (I will explain this a little bit more later).


var MyApp = angular.module('MyApp', []).
  config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
      when('/', {
        templateUrl: 'postList.html', 
        controller: "PostListCtrl"
      when('/post/:id', {
        templateUrl: 'postShow.html', 
        controller: "PostShowCtrl"
      when('/posts/add', {
        templateUrl: 'postAdd.html', 
        controller: "PostAddCtrl"
      when('/post/:id/edit', {
        templateUrl: 'postEdit.html', 
        controller: "PostEditCtrl"

Now, if you look at the templateUrls above, you might wonder how this can truly be a single page app. The answer lies in the fact that these do not refer to actual html files, but rather a special script template that Angular uses. This is the real magic.

views/index.jade (written as html for everyone’s benefit)

<header><!-- banner, nav bar, etc --></header>

<section ng-view=""></section>

<script id="postList.html" type="text/ng-template">
  <h2>Post List Page</h2>
  <div class="post-preview" ng-repeat="post in posts">
    <a class="post-title" href="/post/{{post.post_id}}">
    <span class="post-details">
      Authored by {{}} on {{}}

<script type="text/ng-template" id="postShow.html">
  <div ng-bind-html-unsafe="post.post_body"></div>

<script id="postAdd.html" type="text/ng-template">
  <h2>Add New Post</h2>
    <input type="text" name="post_title" ng-model="post_title"/>
    <textarea type="text" name="post_body" ng-model="post_body"></textarea>
    <button ng-click="submitPost()">Add Post</button>
<script id="postEdit.html" type="text/ng-template">
  <!-- etc, etc -->

This technique is very much like <div data-role="page"> from jQuery Mobile. The last thing left to play with are the Angular controllers.


MyApp.controller('PostListCtrl', function PostListCtrl($scope, $http) {
    success(function(data, status, headers, config){
        $scope.posts = data.posts;

MyApp.controller('PostShowCtrl', function PostShowCtrl($scope, $http, $routeParams, $location) {
    success(function(data, status, headers, config) {
        $ =;
      }else {
        //handle error/redirect to list

MyApp.controller('PostAddCtrl', function PostAddCtrl($scope, $http, $location) {
    $scope.submitPost = function() {
      $'/api/posts', {
          post_title: $scope.post_title,
          post_body: $scope.post_body
        }).success(function(data, status, headers, config) {
          }else {
            //do something about the error

//all other controllers omitted for brevity

 App Flow Summary

Let’s walk through this from the user perspective. You click a link to The request matches the catch-all route ‘*’ and so the index page is returned. Like normal, the browser will follow up with any css/image/js resource requests which match the express.static() directive. But then the angular app fires up. It looks at the location.path(), matches it with ‘/’ and loads the PostList.html template into the ng-view, and then calls the controller. The PostListCtrl immediately makes an XHR for a list of posts, which it assigns to the $scope.posts variable. Thanks to Angular’s two-way binding, the page automatically generates all the DIVs to match each post.

Something interesting to note that should hopefully make all of this gel is what happens when you click the link for /post/6. If you’re already on the index/list page, no request is made to the server — the app just switches pages, triggers the new controller and the ajax request gets made and the page gets filled out. Now, what if you were started with this url? For example, if it was bookmarked or someone sent you a link directly to the post.

When you start by requesting something like /post/6, the request does go to the server, but it won’t match any routes because, as I said earlier, we set up our api to not overlap with the client routes. Instead, that wonderful catch-all route at the bottom serves back the index file. When Angular takes over, it matches location.path() against the client route for PostShow.html and shows that page first instead of the List page… and then goes and gets you a beer, because that’s just how awesome Angular is.

 Finally, Getting Responsive

I think one of the easiest ways to get started with responsive design is to use either Twitter Bootstrap or Zurb Foundation. Each of these provide a bunch of boilerplate css to get started, and can be extended with basic JavaScript widgets. The most essential feature, however, is a responsive grid system for defining the layout of your page. Media queries are already in place to shuffle the design around at the various breakpoints, which saves a lot of trouble.


For more information, the best starting point for something like this is the angular-express-seed and the angular-express-blog (based on seed). Also worth checking out is the recently released Yeoman project, which helps setup highly robust web app stacks of this vein. Yeoman has code generators to build skeleton apps based off of different client-side frameworks, such as Angular, Backbone, or Ember. Brian Ford just did a nice write-up of using Yeoman for Angular apps.

Posted in Javascript | Tagged , | Leave a comment

Angular.js Services

Here are two simple ways to instantiate services to an Angular.js application. I came to these following a conversation with @PascalPrecht. The actual code is derived from a jsfiddle by Pawel Kozlowski.

The standard definition of an app in Angular 1.0 is as follows:

var app = angular.module('myApp', []);

All Angular apps then require one or more controllers which hold the data and functions available for a particular section of DOM.

app.controller( 'AppCtrl', function AppCtrl($scope) {
  $ = 'Guest';

The HTML for this looks like the following:

<!doctype html>
<html ng-app="myApp">
    <section ng-controller="AppCtrl">
      <h1>Hello, {{name}}</h1>
        <label for="name">My Name is</label>
        <input name="name" ng-model="name" type="text"/>

Now, say we need to create a service module to do something with our app. For instance, manipulating some of our controller data. Suppose we want to reverse our name variable.

The first approach is to use .service(), which creates a new function object.

app.service('nametrickService', function() {
  this.reverse = function(name) {
    return name.split("").reverse().join("");

The alternative method is .factory(), which gives you a space to run some one-time code prior to returning an object.

app.factory('nametrickFactory', function() {
  return {
    reverse : function(name) {
      return name.split("").reverse().join("");

So now we’ve declared two services which have a function we want to access within our app. We need to inject these services into our controller. Additionally, we’re going to set up two $scope-level functions that call our services.

app.controller( 'AppCtrl', function AppCtrl($scope, nametrickService, nametrickFactory) {
  $ = 'Guest';
  $scope.reverseNameService = function() {
    $ = nametrickService.reverse($;  
  $scope.reverseNameFactory = function() {
    $ = nametrickFactory.reverse($;  

In our html, we can now add buttons to call this.

<button ng-click="reverseNameService()">Reverse Name via Service</button> 
<button ng-click="reverseNameFactory()">Reverse Name via Factory</button> 

So these are my two favorite techniques for adding services to angular.js. The .service() method is a bit more simple, but if you need to do any one-time setup, such as initializing some other resources or libraries, the .factory() method would allow you to execute code prior to returning the service object.

For the full example, have a look at this jsfiddle.

Posted in Javascript | Tagged | Leave a comment

Drupal Workbench & User Profiles

Drupal is a wonderful system for business/organization web sites when you want users managing content without bothering the developer. User roles, permissions, content types, and views are amazingly powerful in combination. A couple years ago, I launched a large site with Drupal 6 and have spent little time in Drupal since, but a new project has brought me back. I want to share an interesting challenge I faced getting started.

On this new project, I needed to allow a certain class of users to create profiles that would be approved before hitting the live internet. Drupal user accounts can be extended to add additional profile fields, and there is also the Profile2 module that does this a bit better, but it is not possible to require approval before posting. With Drupal 7 comes an awesome new module suite called Workbench. Workbench is the answer for Drupal content moderation. You can set up multiple status levels and transitions, and control who edits what content. The only problem with Workbench is that it only works on Nodes. User profiles aren’t nodes! The only way to make this work is to use a content type for user profiles.

Allow One Instance of Content Type

Ok, so we’re going to use a content type for user profiles. First question is how do you enforce that users only create a single instance of a particular content type. This turned out to be fairly straight forward thanks to the Rules module. Start with a user role called Profile Creator that only has the permission to create the profile content type. Ensure this role is assigned to your users. Then set up the following pair of rules.

Add Profile Rule:
Event - After saving new content
Condition - Content is of type: Profile
Action - Remove user role (Profile Creator)

Delete Profile Rule:
Event - After deleting content
Condition - Content is of type: Profile
Action - Add user role (Profile Creator)

Customize Menu Link

The next thing I wanted to do was set up a My Profile menu link in the User Menu. If no profile has been set up by that user, it would say Create Profile and link to the appropriate path for that. I chose to do this with a custom module I called Dynamic Menu Links. I use it for a couple of links that need a special set of rules.

The hook we need to access is the _menu hook.

function dynamic_menu_links_menu(){
  $items = array();

  $items['profile'] = array(
    'title'=>'My Profile',
    'access callback'=>'my_profile_access',
    'title callback'=>'my_profile_title',
    'page callback'=>'my_profile_page',

  return $items;

Next, we define the three callbacks referenced above. The access callback screens the user for permission to see the link. The title callback determines the text to use for the link, and the page callback directs us when the link is clicked. There may be a more optimal way to accomplish this, but a quick database query can tell us whether a profile already exists for the user. I set up my Pathauto pattern for profiles to be profiles/[node:author:name].

function my_profile_access(){
  global $user;
  return $user->uid;

function my_profile_title() {
  global $user;
  $result = db_query('SELECT nid from {node}
    WHERE type=:type AND uid=:uid limit 1',
      array(':type'=>'profile', ':uid'=>$user->uid));
    return 'My Profile';
  return 'Create Profile';

function my_profile_page(){
  global $user;
  $result = db_query('SELECT nid from {node}
    WHERE type=:type AND uid=:uid limit 1',
      array(':type'=>'profile', ':uid'=>$user->uid));

So now that we have menu links for “My Profile” and “Create Profile”, and the user is limited to only one instance of Profile content type, it’s starting to behave like we would expect for a profile system. The rest of the details rely on setting up Workbench.

Posted in Drupal | Leave a comment