Using Backbone.js

Like Require, Backbone has many pre-existing and excellent tutorials. In particular Artur Adib’s tutorial is what made it all become clear to me and Aaron Hardy’s article on JavaScript Architecture continues to make me happy.

Still here? Are there not plenty of links to fit your information needs above? You curious fellow/fellette. Let’s have a crack at an overview of Backbone then.

Backbone’s structure

Backbone introduces four types of Object to your JavaScript. Models, which represent a single entity of data. Collections, which contains multiple Models. Views, which handle the presentation of your data. And Routers which are special and cool and not going to come up again in this post.

Starting with a Model

Creating a Model is really easy in Backbone.
var Developer = Backbone.Model.extend();
Boom. A Developer Model. We can get fancy though

var Developer = Backbone.Model.extend({
	defaults: {
		name: 'A Dev'
	}
});

Here we are defining a pair of default attributes. This means that any Developer created will have these attributes set to these values unless specified otherwise. We are not defining a complete list of possible attributes, merely the ones we want all examples of the Model to have and their default values.

There’s more we can do with a Model, but we’re not going to get into that now.

Creating a Collection

If you’re still reeling from creating a Model, then creating your collection can be a bit of a breather for you.

var DeveloperCollection = Backbone.Collection.extend({
	model: Developer
});

Done. We’ve created a collection and told it what it’s a collection of. Again, there’s more fancitude available but we’re not going to touch it today.

Displaying data with a View

Backbone is very close to a Model-View-Controller pattern. The thing it’s missing is a Controller. That’s becuase responsibilty for Control is placed partly in the Collection, but mostly in the View.

The View is responsible for rendering html to display your models and taking in user input. This means that even even at its most basic, there’s a little more to a View than a Model or Collection. Let’s take a look:

var DevelopersListView = Backbone.View.extend({
	el: $('#content'),
	initialize: function(){
		_.bindAll(this,'render', 'appendItem');
		this.collection = new DeveloperCollection();
		this.render();
	},
	render: function(){
		var self = this;
		_(this.collection.models).each(function(item){
			self.appendItem(item);
		});
	},
	appendItem: function(item){
		var template = _.template('<li><%= name %></li>');
		var templateVariables = {
			name: this.model.get('name')
		};
		$('ul', this.el).append(template(templateVariables));
	}
});

The el attribute tells the View where in the page to insert itself. I’m not sure about using a jQuery selector here, I suspect it’s not necessary but it’s what Artur did and I’m not going to argue right now.

The initialize function is run when the View is instantiated. It is doing three things. First, it’s calling bindAll on its functions. bindAll is an Underscore function which fixes the context of functions. What that means is, whenever we call a bound (binded?) function, the value of this is fixed to the object passed as its first parameter. In this case, it’s the View.

Second, initialize instantiates a Collection to use. Third and finally, it calls its own render function.

The render function iterates through the collection using Underscore’s each function and calls its own appendItem function on it.

The appendItem function uses an Underscore template and the contents of the object passed to it, a Model, to add a DOM element to the page. This could and should be a separate file, but for now it can just be a String.

So that’s all very good and lovely, except right now we’re using an empty collection and have no way to add anything to it. Let’s fix that by adding a bit more to the View

var DevelopersListView = Backbone.View.extend({

	el: $('#content'),
	events: {
		'click button#add': 'addItem'
	},
	initialize: function(){
		_.bindAll(this,'render', 'addItem', 'appendItem');
		this.collection = new DeveloperCollection();
		this.collection.bind('add', this.appendItem);
		this.render();
	},
	render: function(){
		var self = this;
		_(this.collection.models).each(function(item){
			self.appendItem(item);
		});
	},
	addItem: function(){
		var nameIn = $('#name').val();
		if (nameIn) {
			this.collection.add({name:nameIn});
		} else {
			this.collection.add();
		}
	},
	appendItem: function(item){
		var template = _.template('<li><%= name %></li>');
		var templateVariables = {
			name: this.model.get('name')
		};
		$('ul', this.el).append(template(templateVariables));
	}
});

So, what’s new here? We’ve added an events object, an addItem function and a couple of extra bindings. Let’s start on the addItem function. We’re looking at the DOM object with id name, taking its value and adding it to the collection. We’ve wrapped this add in an if statement so that if the name input is empty, we’re using a default.

So, how about our new bindings? Well, addItem has been added to the bindAll. Pretty much every function attached to your View should be in the bindAll. We’ve also called bind on an add event for the new collection. Confusingly, this is not an Underscore bind. This is a function of the Backbone collection Object. We’re saying that when an add event is fired by the DeveloperCollection object, then we should run the appendItem function.

Finally, the events object. This defines all the event bindings associated with the View. We’ve said that when a click event is fired on the button with id add, we run the addItem function.

All this needs now is some html including a name input, an add button and a content div

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>One Page Web App</title>

	</head>
	<body>
		<section id="content">
			<h1>Really Useful Dev List App</h1>
			<input type="text" id="name"></input>
			<button id='add'>Add List item</button>
			<ul></ul>
		</section>
		<script src="backboneapp.js"></script>

	</body>
</html>

Ta-Da! That’s it for now, a fully functional if pointless little Backbone app.

Advertisements
Tagged , , , ,

One thought on “Using Backbone.js

  1. […] is the same html as my Backbone post but with a require script tag instead of an ordinary […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: