An Intro to Backbone.js: Part 1 – Models and Collections
JavaScript interpreters are FAST, and they’re in every browser out there. You can run a rich application in the browser using only open technologies and built in browser-functionality, today.
Backbone.js can help build it. It’s a light-weight MVC for the browser – only ~1000 lines of code, and it’s clean.
There’s no magic. It’s mostly just a structure for the code you write – not a bulky collection of widgets and doodads. It’s fast to learn, and lets you work with whatever technologies you’re already comfortable with.
Trying Out Backbone
If you’re looking to try it out, you’re going to need to load Underscore.js first. It’s Backbone’s only major dependency.
Oh yeah, and Backbone does not have anything to do with the DOM, although it does have some loose dependencies on the $ and ajax calls of jQuery/Zepto. If you aren’t using jQuery or Zepto then you’ll need to do a little more work (like 10 lines of code). I’ll go over the particulars in the next post. For now, play nice and just use jQuery or Zepto if you feel like following along.
What’s going on in there?
There are five main prototypes in Backbone.
- Backbone.Collection – A little more than what you’re thinking.
- Backbone.Model – ActiveRecord implementation, but it’s got a url!
- Backbone.Controller – More or less exactly what you’re thinking.
- Backbone.View – If you’re from Rails, then it’s not what you’re thinking.
- Backbone.Events – Inherit from this guy to give your objects PubSub!
In this blog post we’re going to look at Models, Collections, and Events.
Backbone.Model:
An implementation of the ActiveRecord pattern, but using JSON and a RESTful API instead of directly interfacing with a database.
So let’s say that we’re working on a donut app, and we want to be able to describe our donuts!
// We extend the Backbone.Model prototype to build our own
var Donut = Backbone.Model.extend({
// We can pass it default values.
defaults : {
name : null,
sparkles : false,
cream_filled : false
},
url : function() {
// Important! It's got to know where to send its REST calls.
// In this case, POST to '/donuts' and PUT to '/donuts/:id'
return this.id ? '/donuts/' + this.id : '/donuts';
}
});
That’s analogous to defining a model class in Rails. Now let’s put it through it’s paces a little.
// Instantiating
var bostonCream = new Donut({ // attributes passed to the Donut constructor will override the defaults
name : "Bostan Cream",
cream_filled : true
});
// Updating and retrieving attributes
// Actually, let's put sprinkles on that...
bostonCream.set({ sprinkles : true });
// Saving
bostonCream.save(); // this will now POST to the RESTful interface.
Backbone.Model#save is an asynchronous method. So you’ll need to provide a callback. The following code assumes success.
// Now that it's saved it'll have an id..
bostonCream.id;
-> 3, or whatever number your JSON api passed up.
// Wait, what's the name?
bostonCream.get("name");
-> "Bostan Cream"
// Ugh, sprinkles are gross. And there's a typo in the name.
bostonCream.set({
sprinkles : false,
name : "Boston Cream"
});
// Updating
bostonCream.save(); // and now it's a PUT.
// it will put directly to "donuts/3", since that's the URI
// of the model now.
Backbone.Collection:
A collection of models, duh. It’s a little smarter than that. It proxies to Underscore to give you a bunch of sweet list functions for working your data out, and lets you keep an eye on what your models are up to through a bunch of handy events. Plus, if you have a RESTful API you can tie them directly to a collection on your backend. Cool, right?
So let’s work out this donut example a little. If you want to manage a collection of donuts, we can use the same API we were working with earlier…
var Donuts = Backbone.Collection.extend({
model : Donut,
url : "/donuts"
});
var donuts = new Donuts;
donuts.fetch(); // this makes a call to the server and populates the collection based on the response.
The call to collection#fetch is asynchronous, so let’s assume this code is being run after the call is complete.
donuts.at(0); -> gets donuts by index. donuts.get(0); -> gets donuts by id.
And a few examples of the Underscore iterator methods…
donuts.each(function(donut) {
console.log(donut.get("name"));
});
// Select donuts with names longer than 2
donuts.select(function(donut) {
return donut.get("name").length > 2;
});
// Map...
donuts.map(function(donut) {
return donut.get("name");
});
Nested Collections
One of the most common uses for collections is to make them nested. In this case, let’s introduce another model, the “Donut Shop” and let’s say that it has a list of Donuts that it serves.
var DonutShop = Backbone.Model.extend({
defaults : {
name : "Untitled"
},
initialize : function() {
// When you extend a Backbone.Model and give it an initialize function,
// the function is called when you instantiate an instance of your Model.
// The initialize function is used repeatedly in Backbone's prototypes. We'll be seeing this again
this.donuts = new Donuts;
this.donuts.url = 'donut_shops/' + this.id + "/donuts";
}
});
So now if you have an existing donut shop that has been saved to the server, you can go:
donutShop.donuts.fetch();
Backbone.Events:
All of the Backbone core objects give you events to plug in to. For instance, the Collection prototype allows you to bind to “add” and “remove” events.
donutShop.donuts.bind("add", function(donut) {
alert("added " + donut.get("name"));
});
// now adding a donut will trigger the alert
var lemonFilled = donutShop.donuts.add({ name : "Lemon Filled" });
Backbone provides you with the Backbone.Events object as well. So, since Underscore is a prereq of Backbone anyway, you can do fancy nonsense like this…
var application = {};
_(application).extend(Backbone.Events);
// Now your application object has it's own events! For example.
application.bind("fun:had", function() { alert("wee!"); });
application.trigger("fun:had"); // it'll alert "wee!"
There’s part 1. Next time I’ll take you through some fun parts:
- Navigating using Backbone.Controllers
- HashChange routing!
- Creating a view
- Tying a view to model events
- Tying a view to a collection’s events.
If you’re looking to try out Backbone, which I’m guessing you are, here are the relevant links.


Pingback: An Intro to Backbone.js: Part 1 – Models and Collections – Liquid Media « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit
Pingback: links for 2011-01-25 | toshism
Pingback: Pedro Newsletter 28.01.2011 « Pragmatic Programmer Issues – pietrowski.info
Pingback: JavaScript Magazine Blog for JSMag » Blog Archive » News roundup: the performance of feature detection, Mobile Firefox 4 performance, W3C Touch Events
Pingback: Quora
Pingback: Kickass Labs » Blog Archive » Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy
Pingback: jQuery & Backbone.js | IT Zen
Pingback: Loccasions: Going Client-Side with Leaflet, Backbone, and Jasmine » RubySource