Will Little Subscribe

A quick introduction to Backbone.js


As we wrap up the “quick introductions” part of our Introduction to web and mobile development series, here I'll be presenting Backbone.js — a JavaScript framework that plays nicely with jQuery and Ruby on Rails. This post jumps immediately into tying together the multiple markup and scripting languages that we've introduced thus far, so make sure you've at least scanned the previous posts and let's get going.

[Author's note: I wrote the first couple dozen tutorials in this series a few years ago and I'm in the process of updating the content to reflect the evolution of best practices in the industry. Backbone.js has been overtaken by Angular, React, Ember, Meteor, etc… but is still worthwhile to learn as a beginner to grasp the basics of a front-end framework. Please comment if you see anything I missed that should be updated. Thanks!]

OVERVIEW OF BACKBONE.JS

First of all, Backbone.js is meant to help you organize your JavaScript and the manipulation of browser stuff such as the elements in your Document Object Model (DOM) (e.g. <div>, <p>, and <li> tags). If you want to, you can do all the magic yourself (as many developers do) with tools like jQuery and your own object architectures, observers, AJAX calls, etc., but there are serious advantages to using Backbone.js (or other frameworks like Angular.js, Ember.js, Meteor.js, Sails.js, etc…) because — quite frankly — for most apps there is no reason to reinvent the wheel. Helpful classes and methods have already been built for you that you can extend to suit your needs.

Second, Backbone.js does not care what back-end language or front-end template system (more on this below) you are using, it only needs to work withJSON and the standard front-end languages. While this is cool because it's flexible, it makes it difficult for beginners to learn because there are an infinite number of ways to set things up (and thus Googling for help can often land you in someone else's Backbone.js paradigm).

Because of this, we have deliberately chosen to use (and standardize our conventions with) Backbone-on-Rails, CoffeeScript, and Embedded CoffeeScript (Eco) templates. While these are certainly suitable candidates for us to use throughout the rest of these tutorials, you'll also want to look into the templating tool React.js (had I written this tutorial more recently, I likely would have chosen React and followed this basic line of integration).

THE BACKBONE OF BACKBONE.JS

Because it's crazy easy to get lost, at first, when browsing the Backbone.js documentation or Backbone.js tutorials online (most of which expect you to be a software genius of some sort), we'll boil down the different parts for you here and then walk you through building your own app step-by-step later in these tutorials.

When your website is loaded, we'll have something like this in an included CoffeeScript (i.e. something.js.coffee — which, remember, gets transcompiled into pure JavaScript for browsers to read):

$(document).ready ->  
  MyApp.initialize()

What is MyApp and what is .initialize() you ask? Good question. These are also defined in a CoffeScript file you setup:

window.MyApp =
  Models: {}
  Collections: {}
  Views: {}
  Routers: {}
  initialize: -> 
    #do stuff

Oh snap, now this is getting interesting.

MyApp is an object we've defined within the window object (i.e. the top level object in JavaScript that contains the document object, history info, etc.). The initialize function (more accurately, the “method” since it is a function within our object class) has been defined and is ready to do stuff.

Just to make things interesting, we also threw in the other key backbone elements of Backbone.js, namely the models, collections, views, and routers. We'll introduce each one quickly here below.

BACKBONE.JS MODELS

Let's say our app will have users — a common and hopeful goal :). A “user” therefore, like in our Ruby on Rails app, is a model. So, we can define it as such in another included .js.coffee file:

class MyApp.Models.User extends Backbone.Model
  url: '/api/user'
  paramRoot: 'user'

Ok, now we are seriously getting into it (‘told you we'd go quick). Don't worry if you are not picking all this up — but it's important to try to get the basic concepts before we start writing our app later in this tutorial series (at that point this will become much clearer).

Backbone.Model is a backbone.js class that has a bunch of its own convenient methods to use, and we can also define our own or override the defaults. Theurl method, for example, tells Backbone where to sync up our model with our back-end (Rails) model (more on this later). The paramRoot method tells Backbone to wrap all the user's attributes into a ‘user' object when sending data (this is convenient when handling the params on the Rails end of things, which you'll see).

We can (and will) do a lot more here later with the user model (such as adding authentication and validation methods).

BACKBONE.JS COLLECTIONS

Let's say we want to store a collection of users in browser memory and then do things like add, remove, fetch, sync with our back-end server, display them in the browser, etc… This is exactly what Backbone collections are useful for:

class MyApp.Collections.Users extends Backbone.Collection
  model: MyApp.Models.User
  url: '/api/users'
  initialize: ->   
    #do stuff

We setup a collection object class — which has a bunch of useful methods baked in — and the initialize method will get called every time we create an instance of this class (which we'll do below). In the collection here we also define what model this is a collection of, and we let the class know what back-end URL it can visit to fetch users.

BACKBONE.JS VIEWS

So we've setup a model and a collection of models, but in practice this is just data stored in the memory of our visitor's browsers. In order to actually displaythe collection or listen to click or hover actions from our visitors, we need to setup special classes called views:

class MyApp.Views.User extends Backbone.View
  template: JST['users/show']
  events:
    'click .avatar': 'showLargeAvatarImage'    
  render: ->
    $(@el).html(@template(user: @user))
    this
  showLargeAvatarImage: ->
    #code to open the larger avatar image

In this example, we've setup a view that will, upon being instantiated and rendered, be ready to be added to the DOM for a visitor to see. In this case, this would be the HTML element that displays an individual user. The users/show JST (i.e. JavaScript Template) would be our Eco template of this element. It could have an avatar image that, when clicked, showed a larger version. This is what the events method of the view handles for us.

Your head is probably exploding at this point, but this really is the meat of Backbone.js, so nice job getting this far. Again, it will all make more sense once you start building the app for yourself here soon.

BACKBONE.JS ROUTERS

The final core component to Backbone.js apps that we'll quickly introduce here is a router:

class MyApp.Routers.Users extends Backbone.Router
  routes: 
    "show-user/:id" : "showUser"
  showUser: (id) ->
    #code to show the user

In this example if a visitor browsed to, say, /show-user/17, we could take action to show that user however we wanted. The router is meant to read from (and write to) the browsers address bar and respond according to our code. Modern day apps like Facebook and Gmail, for example, use this kind of routing methodology to keep things fast. There's no reason why you can't built apps to do the same.

TYING THEM ALL TOGETHER

Given all these examples above, we now can setup our MyApp object like this:

window.MyApp =
  Models: {}
  Collections: {}
  Views: {}
  Routers: {}
  initialize: -> 
    MyApp.current_user = new MyApp.Models.User()
    MyApp.currentUserView = new MyApp.Views.User()
    MyApp.users = new MyApp.Collections.Users()
    MyApp.usersRouter = new MyApp.Routers.Users() 
    Backbone.history.start(pushState: true)

This is now a clean way to handle users, including a current_user (e.g. if you are logged in), with your Backbone code. The final line above allows you to use your browser's back button to move between different states of your app, even if you never leave the page.

And that's it — at least for a quick introduction. When building a real-life app there are many more views, collections, and models — each with a full set of methods — that you create to mirror your back-end architecture (usually syncing with your database models). As you can see, Backbone.js allows you to build true apps for desktop and mobile browsers that go well beyond the features of simple websites.

- — -

In our next post in this series, we'll describe how to go about setting up the foundation of your idea, your business, your advisors, and your team. Previous post: XML and JSON introduction.