Alex Kinnee

Optimal use of Backbone.js model events and MV* structure to update the DOM

Backbone is a JavaScript framework designed to give a common structure to web applications. Most Backbone apps allow users to change data and save it back to a server. Backbone helps by storing a client-side representation of that data in models, rather than in the DOM.

If you’ve used jQuery in the past to make AJAX calls, you know that the $.ajax method provides a success callback. For a while is was common to make an AJAX call in response to a user action, then update the DOM in the success callback. It’s a common mistake to bring this practice over to the Backbone world, because Backbone’s save method also provides a success callback.

Because of the nature of JavaScript, it is hard to enforce MV* patterns. The best a framework can do is give developers a toolset and hope that they use it correctly.

Below is a poor example of a relationship between a Backbone model and its associated views.

Backbone BAD view model relationship
Keep reading. This is the anti-pattern, not the right way!

Bad view code

updateName: function(new_name) {
	this.model.save({
		name: new_name
	}, {
		success: _.bind(function(model, response, options) {
			this.$('.name').text(model.get('name'));
		}, this);
	});
}

In the above example, the developer called a method on the model and updated the DOM in the success callback. The main problem with this is that any other views associated with this model will not be updated, because they update using callbacks, instead of model events.

Below you’ll find an optimal example of how a view should be updated. It follows this basic rule: views should only update the DOM in response to model events (with the exception of simple UI interactions, like expanding hidden content).

Backbone view model relationship
An optimal approach to data binding in Backbone

Good view code

initialize: function() {
	this.model.on('change:name', this.renderName);
},
renderName: function() {
	this.$('.name').text(this.model.get('name'));
},
updateName: function(new_name) {
	this.model.updateName(new_name);
}

Good model code

updateName: function(new_name) {
	this.save({
		name: new_name
	});
}

This approach is good because it allows developers the flexibility of being able to hook up as many event listeners as they want. Multiple views can be updated, and additional model methods can be called. Properly utilizing model events to update views also allows easy integration with a push service.

There are a few Backbone plugins available which adhere to this methodology and allow developers to easily bind DOM elements to model attributes. Two good examples are Backbone.ModelBinder and Epoxy.js.

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>