Node Tutorial Part 19: Backbone.js

2011-04-04 00:00:00 +0100 by Alex R. Young

Welcome to part 19 of Let's Make a Web App, a tutorial series about
building a web app with Node. This series will
walk you through the major areas you'll need to face when building your
own applications. These tutorials are tagged with

Click to show previous tutorials.


Backbone.js is a library for writing client-side JavaScript. It provides base classes for models,
collections, and views. If you've ever worked on a project with a
library like jQuery and found client-side code becomes unwieldy and hard
to navigate, Backbone.js can help!

Nodepad's simple structure means we're mostly interested in Backbone's
models, collections, and the persistence layer. The persistence layer is
the part that talks to the server, communicating using JSON. The views
are also useful, however. As Backbone's documentation says:

It's all too easy to create JavaScript applications that end up as tangled piles of jQuery selectors and callbacks.

To put it simply, a Backbone application uses models to interact
with data, collections to manage sets of models, and views to
link events to models and generate dynamic HTML based on templates. The
templates are typically hidden HTML, so in our case we'd write stubs in
our Jade templates with display: none, then Backbone views
would be used to clone and populate these HTML fragments with data.

Planning a Backbone Application

Planning a Backbone application is a bit like planning server-side
software -- separate out the data from the views and controllers.

Our application consists of:

  1. A document with an ID, title, and body
  2. A document title row
  3. A list of titles which can be selected, added to, and deleted

This already sounds like Backbone primitives:

  1. Backbone.Model, Document: A document with
    an ID, title, and body
  2. Backbone.View, DocumentRow: A document
    title row
  3. Backbone.View, DocumentList: A list of
    titles which can be selected, added to, and deleted
  4. Backbone.Collection, Documents: A
    collection of documents


Defining models is simple. Use Backbone.Model.extend to
create a new model for your application:

var Document = Backbone.Model.extend({

We can't actually do very much with this yet, and there also needs to be
a collection of models. Collections can be reusable or almost like a
singleton (for collections that are used once). In this case we just
want one list of documents, so I like to create this type of collection
by instantiating a Backbone.Collection:

var Documents = new Backbone.Collection();
Documents.url = '/documents/titles.json';

Each model and collection has a url property -- it can be a
function or a string. Our collection will always use the same URL. And
the reason I'm getting the titles and IDs rather than
/documents.json is because we can load the full document on

I usually use functions when I need to use data to construct the URL:

var Document = Backbone.Model.extend({
  Collection: Documents,

  url: function() {
    return '/documents/' + this.get('_id') + '.json';

As you can see, when loading a Document the URL will
contain our Mongo object's ID.

There's something slightly fiddly still left to do. While we could use
Documents.fetch() to load the titles, the Backbone authors
suggest writing it into the template on the server-side to cut down on
the extra Ajax request. We can do this in views/layout.jade
like this:


The part that reads !{JSON.stringify(documents)} is
actually server-side, and Documents.refresh() just
overwrites all of the collection's data in the browser.


The two main views are DocumentRow and
DocumentList. The DocumentRow view requires
some Jade changes as well. It also uses Backbone.View's
events property to watch for clicks on the document titles:

var DocumentRow = Backbone.View.extend({
  tagName: 'li',

  events: {
    'click a': 'open'

  template: _.template($('#document-row-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');

  open: function() {
    $('#document-list .selected').removeClass('selected');

  render: function() {
      id: this.model.id,
      title: this.model.get('title')
    return this;

The corresponding Jade template looks like this:

  li#document-row-template(style='display: none')
    a(id='document_{{ "{{ id " }}}}') {{ "{{ title " }}}}

The document-row-template part will be hidden and used to
generate several instances of DocumentRow. The
events property in DocumentRow is Backbone's
convention for mapping events to methods. The left-most part,
click is the event, then the rest of the string is used as
the selector to observe. The Underscore method, bindAll is
used to make sure this refers to an instance of
DocumentRow when render is called from an

I'm using the standard Underscore _.template method to
insert each document's value:

_.templateSettings = {
  interpolate : /\{\{(.+?)\}\}/g

To implement displaying a document it simply populates the form fields:

Document = Backbone.Model.extend({
  Collection: Documents,

  url: function() {
    return '/documents/' + this.get('_id') + '.json';

  display: function() {
      success: function(model, response) {
        $('#editor-container input.title').val(model.get('title'));


I've only scratched the surface of Backbone here, but you can see some
of the major components of the library. When using Backbone with a
larger project it may make sense to keep each class in its own file. In
general it can certainly help improve over a monolithic soup of
selectors and callbacks.

I'll continue implementing Nodepad's client-side code with Backbone next

This week's commit was