Backbone.js tutorial

by jacob on November 18, 2010

I have previously covered Backbone.js here, and it seems to be gaining some steam. As of writing, there doesn’t seems to be that many tutorials though, so here one that tries to get you started with the fundamentals, with minimal extra fuzz:

Here‘s the usual demo, you can press the “Add” and “Fake save” buttons as much as you like, they don’t do anything apart from writing to an ad-hoc log at the end of the page.

What’s we’re really interested in for this demo is only the Javascript part. The full source is here. Keep it around for reference when you continue reading.

Fundamentals: Model, Collection and View

There are three fundamental classes (yeah, difficult term in Js, but anyway..) that you need to know about: Backbone.Model is the singular of your data (one row in your db, traditionally speaking) and Backbone.Collection is the plural (typically matched by a query on the server-side). It represents a group of data that has something in common.

Then you have Backbone.View, that 1) should be a visual representation of your data and 2) (optionally) should provide editing affordances for individual Model‘s.

For simplicity’s sake, we begin with defining the simplest possible Model:

var Model = Backbone.Model.extend();

We now have a model class that we can instantiate with a simple

var model = new Model({label:'Test label'});

Backbone models have attributes, which is where the individual pieces of data are stored. The attributes can’t be read/manipulated in the form model.attr_name, but should be read with model.get('attr_name') and written to with model.set(<attributes>) where attributes is a standard Javascript object with one to many attributes to set, e.g. {label: 'Item 1', order: 1}.

model here would have exactly one attribute, label, set to 'Test label'.

Having defined how one data item looks like, you can continue to creating the definition and possible and instance of how several items look:

// Definition, tell it what king of items it will contain
var Models = Backbone.Collection.extend({model:Model});

// Create a models instance with two example items in it (we pretend
// that the JSON list comes from a server:
var models = new Models([ {id: 'm1', label:'Item 1'},
                          {id: 'm2', label:'Item 2'} ]);

Model instances can then be tied to a Backbone.View instance, created similarly:

View = Backbone.View.extend({
    // shortened for brevity..
});

This example is shortened, View creation is more complex, view the full implementation here. Class creation follows the same pattern as when creating Models, though. You can then attach your model instance to a view instance:

var model = new Model({label:'Test label'});
var view = new View({model: model});

The View is responsible for creating itself in it’s .render() method. In the example, the built-in templating mechanism of Underscore.js is used to create a dead-simple DOM fragment: Just one single <input> node.

As can be seen in the Gist, the View also has a clever way of dispatching events in it’s DOM fragment, that’s initialized lazily using the View‘s .events property. The .events property is an object whose keys are jQuery selectors tied to method of the View instance itself. This makes it truly easy to fish for changed values if your view allows the end-user to change it’s values. Instant widgets! Take a look at line 44 in the Javascript to see a simplified example of this.

The not strictly Backbone parts of the example

The Model instance model is initialized with a JSON list of objects that really ought to come from a server. After the models is created, the example uses the fact that Underscore.js functionallity is present in Backbone.Collection to create a simple list of View instances. The view objects are rendered and appended to a <div> element in the DOM to become visible.

As soon as they are visible, the view‘s .events object will dispatch onchange events to the view‘s .change method.

Then two vanilla jQuery event handlers exist for the “Saving” and “Adding” of items. The example monkeypatches Backbone.sync to only log the server calling actions so you can see what Backbone does behind the scenes.

Further reading

To see a more elaborate real-world’y example of Backbone driven code, read Jérôme Gravel-Niquet’s annotated Todo app source code.

The official Backbone.js documentation is, as usual with DocumentCloud projects, very throughly documented, but can be a little daunting at first – hence this tutorial.

Another Backbone.js demo app, also a bit more elaborate with a real backend (Ruby/Sinatra).

Critique

Backbone is a true time-saver. But one thing makes me a little nervous. There doesn’t seem to be any convenient way of doing bulk saves. I’d like to be able to say something along the lines of models.save() on my Collection, having it aggregate all changes and try to post them as a list of objects to the server. Sending the models down the wire one at a times raises some flags both from a transactional integrity and network efficiency perspective.

Do correct me in the comment if I’ve got this wrong about that.

20 comments

Bulk saves (and bulk operations in general) are an interesting exercise in terms of REST, which only defines methods for singular resources.

You can set up your “ChangeSet” as a model in it’s own right, with it’s own url() endpoint, if you’d like to stick to Backbone’s save() method … and at the other extreme, Backbone isn’t intended to be the only mechanism for Ajax communication to and from your server — it’s perfectly alright to make a special jQuery.ajax call for a bulk update.

The reason why a Collection#save() function isn’t implemented out of the box is because it isn’t a common way to model RESTful updates to a set of models. Instead of sending up all the attributes for all of the affected models, it’s much lighter to send up the operation you wish to apply, along with a list of model ids.

by Jeremy Ashkenas on %A %B %e%q, %Y at %I:%M %p. Reply #

Very interesting point, and kind of what I was suspecting. In a previous solution I created a bulk save but noticed that although it worked it did become messy. I will try out the “ChangeSet” method and see how it works out.

by jacob on %A %B %e%q, %Y at %I:%M %p. Reply #

This was just what I needed to get started with Backbone.js (and Underscore.js) — a stripped-down example that covers the basics and lets you build on it from there. Jérôme’s app is great, but it was too much all at once. I’ll move on to it once I’ve got a better foundation. Thanks for providing a simple introduction without all the extras. :-)

by Matthew on %A %B %e%q, %Y at %I:%M %p. Reply #

Thanks Matthew, great to hear!

by jacob on %A %B %e%q, %Y at %I:%M %p. Reply #

[...] The Meta Cloud’s backbone tutorial [...]

by Kickass Labs » Blog Archive » Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy on %A %B %e%q, %Y at %I:%M %p. Reply #

[...] If we reload SpecRunner.html, there will be no failures because we have not actually added any tests at this point. The first step in TDD is to write a test that should fail and then write just enough code to make it pass. For this example I am going to start creating a backbone.js model. There are a few introductory backbone.js tutorials, including this one by the antipodean Thomas Davis. For simplicity’s sake, I’ll be following this more barebones guide. [...]

by getting started for tdd using jasmine and backbone.js | iknuth on %A %B %e%q, %Y at %I:%M %p. Reply #

A perfect, bite-sized introduction to backbone…thanks!

by Thom on %A %B %e%q, %Y at %I:%M %p. Reply #

Thanks Thom!

by jacob on %A %B %e%q, %Y at %I:%M %p. Reply #

Here`s another demo app I created using backbone.js with handlebars and icanhaz templates. It is a complete rails application for those interested in checking out a end-to-end version.

https://github.com/amoln/backbone.js-with-templates-demo

by Amol on %A %B %e%q, %Y at %I:%M %p. Reply #

I am working on a community based resource for Backbone.js tutorials.

Anyone looking for more beginner tutorials can visit;

http://backbonetutorials.com

by Thomas Davis on %A %B %e%q, %Y at %I:%M %p. Reply #

Good stuff. I like that the Backbone.js is starting to become a little ecosystem of it’s own.

by jacob on %A %B %e%q, %Y at %I:%M %p. Reply #

You could create a “save()” method on your view that parse all the models to an array of objects and post them to a custom REST webservice to save all of them at once…

by javi A. on %A %B %e%q, %Y at %I:%M %p. Reply #

Just to echo what others have already said:

Thanks for this little bitesize tutorial. Its exactly what I need to grok Backbone.js, have it running in my browser and see the benefits.

Jerome’s Todo app is great, but a step too far me to grok.

by Ijonas Kisselbach on %A %B %e%q, %Y at %I:%M %p. Reply #

[...] Meta Cloud [...]

by Javascript Resources « Kooljoy.com Blog on %A %B %e%q, %Y at %I:%M %p. Reply #

Thanks for a great tutorial. I tried this example with latest version of Backbone(0.5.3) and it doesn’t work properly. When you click “Fake save”, only 1st item gets added to the log container.

by dmitry on %A %B %e%q, %Y at %I:%M %p. Reply #

Thanks for pointing it out. I’ll have a look at the example shortly, it’s been a while since I tested them and there have been many updates to Backbone since.

by jacob on %A %B %e%q, %Y at %I:%M %p. Reply #

backbone.js is too complicated, knockoutjs its simplier. just try it; http://knockoutjs.com/

by leonardo on %A %B %e%q, %Y at %I:%M %p. Reply #

[...] – Liquid MediaAppleInsider | SproutCore debuts new HTML5 web development toolsBackbone.jsBackbone.js tutorial « the meta cloudBuilding a single page app with Backbone.js, underscore.js and jQuery | &yet | the blogDailyJS: [...]

by List of HTML5 Resources « prasadsambari on %A %B %e%q, %Y at %I:%M %p. Reply #

Leave your comment

required.

required. not published.

if you have one.