Node Tutorial Part 20: Backbone.js

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

Welcome to part 20 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 Persistence

I haven't yet hooked up our interface and models to Backbone's
persistence layer. I generally work by relying on
model.save(attributes) and model.destroy().
The save method knows when to create or update based on if
the id attribute has been set -- remember this, because
prior to this tutorial Nodepad was using _id which
confuses Backbone.

The add/remove document toolbar could use a skeleton Backbone view like

ListToolBar = Backbone.View.extend({
  el: $('#left .toolbar'),

  events: {
    'click #create-document': 'add',
    'click #delete-document': 'remove'

  initialize: function(model) {
    _.bindAll(this, 'add', 'remove');
    this.model = model;

  add: function(e) {
    // TODO: Create a new document

  remove: function(e) {
    if (confirm('Are you sure you want to delete that document?')) {

The destroy method will delete documents using a HTTP
DELETE, the same way as my previous jQuery implementation.
We actually need to instantiate ListToolBar with a model
though, so where should that happen? I decided to put it in the
DocumentRow view:

open: function() {
  $('#document-list .selected').removeClass('selected');
  this.toolbar = new ListToolBar(this.model);

Every time a document is selected, a toolbar will be instantiated. Now
there's a relationship between the toolbar view and the current

We still need to create a new document when the +
button is pressed... This is basically a case of instantiating a
document and calling save:

add: function(e) {
  var d = new Document({ title: 'Untitled Document', data: '' });

  // Add it to the collection

  // addDocument is a new method I've added to DocumentList which just appends
  // the right elements to the unordered list

  // Trigger an open

There's some housekeeping going on there, but notice that we basically
just call save to make Backbone do all the boring Ajax work
for us.


I've also added a view called DocumentControls which
manages updating documents. By now nothing in this should really
surprise you:

DocumentControls = Backbone.View.extend({
  el: $('#controls'),

  events: {
    'click #save-button': 'save'

  initialize: function(model) {
    _.bindAll(this, 'save', 'showHTML');
    this.model = model;

  save: function(e) {
      title: $('input.title').val(),
      data: $('#editor').val()


  showHTML: function(e) {
    // TODO

The line that reads this.model.rowView.render() is just
triggering the DocumentRow to update its contents. For
clarity, it reads like this:

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


I hope it's now clear that working with Backbone and REST APIs can be
less work than a mess of Ajax calls and CSS selectors.

This week's code was commit