Posted on by & filed under javascript, Programming & Development, Tech.

…or “what the heck your company is doing on the front-end?”

At Safari, we like Backbone.js for designing our front-end interactions, including our reading interface. I’m going to shed light on the concepts that I feel are crucial to working with Backbone, if you’re a beginner to it or similar MVC JS frameworks. If you already know a lot of Backbone, this post probably isn’t for you.

Models

Models are the heart of a Backbone project. They are a good place to start when beginning a project.

A model will contain the core data of an application and is often a representationa of a backend database model.

If you have ever written any JavaScript for an API without using an “MVC framework” you may be familiar with writing ajax functions and deferred callbacks. Backbone Models abstract this process and allow you to interact with your server much more simply.

Get() and set()

You can use Model.set() and Model.get() to update and get model attributes before you send them to your server. Model.set() will set a hash change on the model and fire a change event; we’ve set a listener for that event in the initialize function.

Model.get() allows quick access to model attributes.

Use JSON.stringify to read all the attributes of a model.

Save()

Sending your model to your server is done with Model.save(). This will delegate Backbone.sync and perform ajax using the URL we specified in the model.

The attributes parameter is a hash value of the model attributes you want to send. Save options can include {patch:true} to send an HTTP PATCH request; this will modify only the attributes you’re passing in.

Calling save() will immediately trigger a change event and update the model attributes. To avoid this, pass {wait: true} into options to wait for the server before setting the new attributes on your model. You can also pass into the options success and error handlers, or include them in your save function.

Model.validate() is called before Model.save() and allows you to prevent updates if your data is invalid.

Any error that is returned in validate() will cause the save to abort. For example, adding this function to our Cat Model will fail because it fails to pass validation:

Override Backbone.sync

Sometimes you may want to customize how you update your API. You can override Backbone.sync globally (Backbone.sync = function(method, model) … ) or simply attach a sync() function to your model.

It’s helpful to understand how Backbone.sync maps its method handlers:

Now on save() POSTs, you will simply store your model in localStorage.

Events

Sometimes you need to run some code when something in particular happens elsewhere deep inside your code.

Backbone has a great publish/subscribe concept in its Events system. You can map any custom events to your handlers (Backbone recommends namespacing them) and trigger them multiple times, anywhere, by extending Backbone.Events:

On perhaps a simpler note, Backbone.Events is available globally in the Backbone object. So you can just as easily do,

Views

Backbone.Views should handle the layer of logic between your models and the UI. Updates can happen automatically when your model changes. You can easily render JavaScript logic in HTML templates and trigger jQuery events and methods for DOM manipulation in much simpler terms.

The view attaches to #dog-bone in the HTML and creates a reference in the view with this.$el. From there it is often a good idea to ‘cache’ all the jQuery references in variables for later use:

By storing $my_done_bone as a variable, I no longer have to traverse the DOM every time I want to do something with $(‘#my-dog-bone’).

View#events: {} allows us to map jQuery-like events to our handlers. In this case, clicking .my-button simply logs our model attributes.

View#initialize() is run right when the object is created. Inside it, we listen for changes on the model which invoke render. Render passes in our model to the javaScript template which attaches its HTML to #dog-bone (this.$el).

View#template is a reference to an Underscore JS template to which we can add JS variables.

We can now update our UI simply changing some attributes on our cat1 model:

Underscore templates

You can actually use other javaScript templating frameworks, Backbone requires Underscore as a dependency so we use it here. Pretty much it just contains the html you want and the model attributes as javaScript variables.

Underscore templates accept hash objects which is why our model works so well here. But you can also create you’re own hash object and pass it too it,

It’s all just javaScript

I often find that I need to use a Backbone View or Model I created elsewhere in my code but I need to change a few of the methods without changing the original code.

This is where JavaScript prototypical inheritance comes in really handy, as do the JS call() and apply() functions.

In Backbone, when you create a new view or model with extend, you’re defining the prototype for the new object.

This is the JavaScript way of “inheriting” properties that will go into your object and makes it easy to extend your own models and views.

Our new Dog instances will now log ‘Woof woof’ as well as do everything it does in the original View code.

There is more to working with Backbone including Routers, Collections, helpful Underscore functions, organizing Backbone with require.js, testing with Qunit or Jasmine. For that and much I recommend Developing Backbone.js Application.

Tags: Backbone, cat and dogs living together, frontend, Javascript, js,

2 Responses to “Level up in Backbone.js, a powerful JavaScript MVC framework”

  1. Patrick Mulder

    Nice overview, esp. the way you introduce models and collections to start an app with Backbone.js. Also, it might be interesting to mention the Pipefishbook that discusses Backbone in combination with server-side questions and workflow automation.