Backbone: Meet the Model

A common mantra of the web argues that content is king. Content should frame layout, typography, and can influence technical decisions to some degree. Although this statement has been raised to cliche status, the concept is just as relevant when writing client-side applications.

Having a powerful client-side data layer provides a solid foundation to build work upon. The DOM should not be the main reference point for information in a web application. This is where the Backbone.Model comes in; to provide a set of useful tools for managing data. In this article I'll go over setting up and using what I see as heart of Backbone: the model.

 1 var Widget = Backbone.Model.extend({
 2     defaults: {
 3       name: 'Widget',
 4       units: 'kilos',
 5       weight: 500
 6     },
 8     validate: function(attrs, options) {
 9       // Make the name field mandatory
10       if (! return 'Widgets require a name';
11     }
12 });
14 var cog = new Widget({ name: 'Cog', weight: 200 });
16 "This widget is a " + cog.get('name'); //=> "This widget is a Cog"

Whenever Model.set is invoked, a couple of things happen in the background. After validating that information is correct (something that only occurs if you have specified a validate function), the model updates itself and broadcasts a couple of events.

 1 var cog = new Widget({ name: 'Cog', weight: 200 });
 3 cog.on({
 4   'change': function() {
 5     console.log('global change');
 6   },
 8   'change:name': function() {
 9     console.log('name change')
10   },
12   'invalid': function() {
13     console.log('invalid!')
14   }
15 });
17 cog.set('name', 'Cog 2.0 XLS');
18 // => trigger 'change', 'change:name'
20 cog.set('name', '', { validate: true })
21 // => trigger 'change', 'change:name', 'invalid'

In this example, the on method is utilized to subscribe to events occurring internally to our cog model. When the name attribute is set to a new value, the model triggers a 'change' event, and a 'change:name' event. Deeper behind the curtain the Backbone.Events module iterates over a list of the known subscriptions to these events and executes the behavior specified in the callback function, much like a jQuery DOM event:

1 // Pretty similar, right?
2 $('a').on('change', doSomething);
3 cog.on('change', doSomething);

This is very powerful; it gives us a great tool for separating the interface of an application into specific concerns. The model can focus on being the best way to keep track of information, and the interface can strictly stick to determining the best way to portray that information to a user.

Cool stuff you can do with Backbone Models

Do something when the Model is first created

1 var FancyCog = Cog.extend({
2   initialize: function() {
3     console.log('engaging thrusters');
4   }
5 });
7 var fancy = new FancyCog();
8 //=> 'engaging thrusters'

Recall the last value of a given attribute

1 var cog = new Widget({ name: 'Cog' });
2 cog.set('name', 'New and Improved Cog');
4 cog.previous('name') //=> 'Cog'