This article briefly discusses how the Backbone.View class is normally used and then introduces a new class that helps makes it easy to synchronize your models and views.

The Backbone.View class helps you do a couple of important things that I’ll discuss in very brief detail:  (I assume that you are already familiar with Backbone.Views)

  • Create browser DOM elements
  • Listen to DOM element events
  • Listen to model events

Create browser DOM elements:

Backbone.View objects have a default view.el field that is a DOM element.  By default it’s a <div> but you can override it to be any type of element you want.  Normally, the View.render( ) function’s main job is to fill the view.el with DOM elements that make up the view.

The view also has a view.$el function which is just shorthand for $(view.el).  In the example below, the render function just creates a input DOM element and appends it to the view’s el property – which is just a div.  Nothing will be rendered in the browser at this point.  The calling function would probably add the views.el property somewhere in the browser’s DOM to have it actually show up for the user.

  render: function() {
    this.$el.html('Enter your name: <input type="text"/>);
    return this;

In almost all situations, you won’t inline your html inside of your view classes.  Instead, you’ll have separate html files that are your html templates.  Html templates are then passed to the underscore.js template function which can be passed parameters that are interpreted and html with injected variable values is then returned to be rendered as DOM elements.

Listen to DOM element events:

Backbone.View class lets you define an events hash.  The keys of the events hash are jQuery events followed by jQuery selectors.  The values of the events hash are function call backs that are invoked when the event is raised.

The events are defined as jQuery delegates.  This is nice because delegates are a fairly efficient eventing mechanism that are also dynamic.  When your view.el contents are swapped out, the jQuery delegates don’t need to be refreshed.

Listen to model events:

The Backbone.View class typically listens for when it’s model changes and then calls the view.render( ) function as shown below.

SomeView = Backbone.View.extend({    initialize: function(){
    this.model.on('change', this.render, this);

  render: function() {
    return this;


Problems with the typical backbone View code:

For smaller applications, the approach described above works well.  Especially in these type of situations:

  • The application’s models don’t change very often
  • The application’s pages are frequently refreshed from scratch from the server
  • Model’s aren’t shared between different views

As applications become more complex though, calling render( ) too many times can be wasteful.  The old DOM elements are just thrown away.  Also, you usually have many read-only or editable fields on a page and plumbing them up manually can be a pain in the butt.  Life gets worse when you have special formatting or conversion between how the model stores data and how the view renders the data.

Moving data from the view to the model can be performed in bulk with something like the jQuery serializeArray function but this won’t be ideal when you want other visible views to update immediately instead of on some commit.  serializeArray doesn’t any mechanism to allow you to convert view formats into model formats either.

The ModelBinder:

The ModelBinder class is designed to make it easier to synchronize your views and models together.  It eliminates a few of the problems described above.  When a view’s model changes, the entire view isn’t re-rendered.  Instead, individual elements are refreshed to have the current model values.  When a view’s element changes, the corresponding model attribute is updated.

The  ModelBinder class has the following public functions:

// no arguments passed to the constructor

// model is required, it is the backbone Model your binding to
// rootEl is required, is the root html element containing the elements you want to bind to
// bindings is optional, it's discussed a bit later
bind(model, rootEl, bindings);

// unbinds the Model with the elements found under rootEl - defined when calling bind()

Typically, ModelBinders will be used like this:

SomeView = Backbone.View.extend({ 
 initialize: function(){ this._modelBinder = new Backbone.ModelBinder(); }, 
 render: function(){ this.$el.html(this.template()); this._modelBinder.bind(this.model, this.el); }, close: function(){ this._modelBinder.unbind(); } }); 


Typically, a view will hold onto model binder instances because the view should call unbind( ) when the view closes.  Otherwise you’ll end up with zombie views that don’t die – you would have the same issue if you just relied on traditional model change events.    The view’s render( ) function will only need to be called once.  The template( ) function will not need to be passed any arguments because the ModelBinder will inject the proper model attributes inside the corresponding DOM elements under the view.el.

In the example above, the bind( ) function’s 3rd argument is undefined.  When the bindings argument is empty, the ModelBinder will locate all of the child elements (recursively) underneath the rootEl that have a “name” attribute defined.  For each of the found elements, the element’s name attribute will be bound to the model’s attribute.

So, a rootEl’s child element :  <input type=”text” name=”phone”/>   will be bound to

The ModelBinder bindings parameter:

The 3rd parameter to the bind( ) function should follow this syntax:

// Key: a model attribute         Value: a jQuery selector
{  phone:                         '[name=phone]' }

In the example above, the is bi- bidirectionally bound to DOM elements with a name attribute that equals “phone”.  The jQuery selector can be any valid jQuery selector statement.  The ModelBinder only expects that a single DOM element is returned – multiple elements is OK.

By default, the DOM element’s text or html is bound to the model (depending on the DOM type) but you can also bind to arbitrary DOM element attributes like the example below by using the “elAttribute” option:

// Key: a model attribute         Value: an element binding definition
{  isAddressEnabled:              {selector: '[name=address]',  elAttribute: 'enabled'} }


You can also format/convert bound values with a “converter” option as shown below:

// Key: a model attribute         Value: an element binding definition
{  phone:                         {selector: '[name=phone]', converter: phoneConverter }  }

The phoneConverter in the example above is a function that the ModelBinder will invoke when it copies values from the model to the view or the view to the model.  Converters are passed 4 values as shown below.

phoneConverter: function(direction, value, attributeName, model){ ... }

The direction is either ModelToView or ViewToModel.  The converter can exist on your model instances or in some generic utility function because it’s passed the model as a parameter.  For read-only elements, you can ignore the direction because it’s always ModelToView.

You can use the “elAttribute” option along with the “converter” option when creating your bindings.  The “converter” is invoked before the “elAttribute” value is set.

The elements can also be defined as an array as shown below:

// Key: a model attribute         Value: an array of element binding definition
{  phone:                         [{selector: '[name=phone]'}  {selector: '#phone'}] }

In the example above, we bound to DOM elements that  have a name of phone and DOM elements that have an id of phone.

Since you can explicitly define your binding scope, you can do things like have nested backbone views.  Even if the views have DOM elements with the same name.  You can also use the ModelBinder as a partial view-model binding solution but still have custom logic for really complicated situations that the ModelBinder can’t handle.

If this sounds useful to you, you can try it out here: