JavaScript & AJAX

Build a Contacts Manager Using Backbone.js: Part 4


In part four of this series, we saw how easy it is to add and remove models from our collection, and keep the page updated in sync with the changes. In this part, we're going to look at editing existing model data.

Getting Started

We'll start out by adding another simple button to the template, which will enable editing of its data:

<button class="edit">Edit</button>

As we are adding this button to our existing template, we can also add an entirely new template that can be used to render an editable form in which the model data can be changed. It's very similar to the exiting template, and can be added to the page after the existing template:

<script id="contactEditTemplate" type="text/template">
<form action="#">
    <input type="file" value="<%= photo %>" />
    <input class="name" value="<%= name %>" />
    <input id="type" type="hidden" value="<%= type %>" />
    <input class="address" value="<%= address %>" />
    <input class="tel" value="<%= tel %>" />
    <input class="email" value="<%= email %>" />
    <button class="save">Save</button>
    <button class="cancel">Cancel</button>

The new template consists mostly of <input> elements that expose the editable data. We don't need to worry about labels for the elements, but instead use the data from the model as the default values of each input. Note that we're using a hidden form field to store the type attribute of the model, we'll use this to set the value of a <select> that we need to add using our script instead of having the template render it.

Next we can bind some event handlers for the new buttons we've added; update the events object in the ContactView class so that it contains the following new bindings:

"click button.edit": "editContact",
"change select.type": "addType",
"click": "saveEdits",
"click button.cancel": "cancelEdit"

Don't forget to add the trailing comma to the end of the existing binding! These are very similar to the bindings we've used before; each key:value pair simply specifies an event to listen for and a selector to match the element that triggers the event as the key, and the event handler to execute on detection of the event as the value.

Switching a Contact Into Edit Mode

In the same way that we stored a reference to the template function under the template property of our ContactView class, we should also store a reference to the template function that we'll use to switch the contact into edit mode. Add editTemplate directly after the template property:

editTemplate: _.template($("#contactEditTemplate").html()),

Now we can add the event handlers themselves, which should also go into the ContactView class after the existing deleteContact() method. First, we'll add the editContact() method:

editContact: function () {

    var newOpt = $("<option/>", {
        html: "<em>Add new...</em>",
        value: "addType"    
    }), = directory.createSelect().addClass("type")


We start out by rendering our new editTemplate that we added to the page using Underscore's template() method in the same way that we added each contact using the standard display template.

In order to make editing the type of contact easier we can render a select box that lets the user switch easily between existing types, but we also want to cater for the possibility that the user may want to add a new type. To allow for this, we'll create a special option for the select box with the text Add new... and a value of addType.

We then create the new <select> element using the createSelect() method of our master view, which if you recall from the last part in this tutorial will return a <select> element containing an <option> for each unique type in the collection. We give it a class name, and to get the <select> element to show the existing type of the contact being edited we set its value to the value of the hidden <input> we added in our template. We then insert the new <select> after the <input> for the contact's name. The new select element is added as a property of the view instance so that we can interact with it easily.

Once we've added the <select> element for the contact's type, we can then remove the hidden field so that it doesn’t interfere with saving the edit, which we'll look at shortly.

At this point, we should now be able to click the edit button in any of our contacts and have the contents of that contact converted into a form:

Adding a New Type

One of the event bindings we added was for the change event of the type select box, so we can add a handler which replaces the <select> box with a standard <input> element:

if ( === "addType") {;

    $("<input />", {
        "class": "type"

When the <select> element's value changes we first check whether its value is addType and if so, we remove the element from the page and create a new <input> element to replace it. We then insert the new element using jQuery's insertAfter() method and focus it ready for text entry.

Updating the Model

Next we can add the handler that will take the changes made in the edit form and update the data in the model. Add the saveEdits() method directly after the editContact() method that we just added:

saveEdits: function (e) {

    var formData = {},
        prev = this.model.previousAttributes();

    $("form").find(":input").add(".photo").each(function () {

        var el = $(this);
        formData[el.attr("class")] = el.val();

    if ( === "") {



    if ( === "/img/placeholder.png") {

    _.each(contacts, function (contact) {
        if (_.isEqual(contact, prev)) {
            contacts.splice(_.indexOf(contacts, contact), 1, formData);

First of all, we create an empty element to store the data that has been entered into the form, and also store a copy of the previousAttributes of the model that belongs to the view we're working with. The previousAttributes property of models is a data store that Backbone maintains for us so that we can easily see what an attribute's previous attribute data was.

We then get each input element from the form using a combination of jQuery's find() method and the :input filter, which gives us all of the form fields. We don't want the cancel or save <button> elements though, so we remove them from the selection using jQuery's not() method.

Once we have our collection of fields, we iterate over them using jQuery's each() method and for each item in the collection, we add a new key to our formData object using the current item's class, and a new value using the current item's value.

When we convert the editable contact back into a normal contact, we don’t want to lose the default photo if a new photo has not been chosen. To make sure we don’t lose the default photo, we can delete the photo property from our formData object if its value is blank.

Backbone models have a setter method that can be used to set any attribute.

Backbone models have a setter method that can be used to set any attribute. In order to update the model's data we just call its set() method passing in the formData object that we have prepared. Once this is done we call the view's render() method and our newly updated model will be rendered back to the page, with any updated information from the form.

As we have done previously, we need to update the data stored in our original contacts array so that filtering the view doesn’t lost any changes we have made. We do this in a very similar way as before, first checking whether the photo property has the default value and removing it if so, and then using a combination of Underscore's each() and isEqaul() methods to find the item in the contacts array that has changed. This is where we use the previousAttributes that we saved earlier; we can't use the current model anymore because its attributes have just been updated.

We use the native JavaScript's splice() function to update the contacts array. As before, we obtain the index of the item to update using Underscore's indexOf() method as the first argument to splice() and set the function to update a single item using the second argument. This time we supply our formData object as the third argument. When splice() receives three (or more) arguments, the third argument is the data to replace the data that has just been removed.

Cancelling the Edit

We have one button left that we need to add a handler for – the cancel button. This method will be very simple and will just switch the contact back into non-edit mode, using the original data from the model. Add this method after the saveEdits() method:

cancelEdit: function () {

That's all we need to do! We already have a method that takes a model and renders it as a view on the page, so we simply call this method and the original model data will be used to recreate the original contact. This is useful because even if someone changes the data in the form fields while the contact is in edit mode, when the cancel button is clicked, these changes will be lost.


In this part of the tutorial we've looked at how we can update the data of an existing model rather than creating a whole new model. To do this we essentially just need to call a model's set() method and pass in the new attributes that we wish to set.

As with Backbone however, we've only covered a small fraction of what these libraries provide, there is so more that we can use when building complex applications on the front-end.

As we saw however, we also need to think about how we can change the view to allow the visitor to enter the data that will be set as the new attributes. In this example, we achieved this by creating another template to handle rendering a form pre-filled with the existing attribute data which the user can overtype to change.

Over the course of this series, we've looked at all of the major components of Backbone including Models, Collections, Views and Routers and Events. We've also looked at some of the methods and properties provided by Backbone that we can use to interact with the different constructs to produce an integrated, functioning application, albeit a basic one.

As well as learning some Backbone basics, one of the most important aspects of the tutorial was in how the application is structured, with all of our code organised in a logical and consistent way. Applications written in this style can be much easier to return to and maintain on the long-term. Much of our functionality was event driven, either in response to the actions of the visitor in the form of UI event handlers, but some were also driven by changes to the collection and triggered manually at the appropriate point in our code.

We've also looked at some of the utilities provided by Underscore which has given us easy ways to work with the objects and array that form the foundation of our application. As with Backbone however, we've only covered a small fraction of what these libraries provide, there is so more that we can use when building complex applications on the front-end.

Related Posts
  • Web Design
    Creating Friendlier, “Conversational” Web FormsForm retina
    Web forms are constantly a hot topic when it comes to web design and user interaction. The reasons for this are vast, but one of the more obvious reasons is that forms are the most basic way for a user to input information into your application. In this article, we'll discuss a few techniques that allow your forms to respond to the user's input, while helping to obscure unnecessarily confusing or overwhelming elements.Read More…
  • Code
    iOS SDK
    Working with NSURLSession: Part 3E548b preview image@2x
    In the previous tutorials, we explored the fundamentals of the NSURLSession API. There is one other feature of the NSURLSession API that we haven't look into yet, that is, out-of-process uploads and downloads. In the next two tutorials, I will show you how to create a very simple podcast client that enables background downloads.Read More…
  • Web Design
    Walk Users Through Your Website With Bootstrap TourTour retina
    When you have a web application which requires some getting used to from your users, a walkthrough of the interface is in order. Creating a walkthrough directly on top of the interface makes things very clear, so that's what we're going to build, using Bootstrap Tour.Read More…
  • Code
    JavaScript & AJAX
    Ember Components: A Deep DiveEmber components retina preview
    Ember.js is a JavaScript MVC framework that allows developers to create ambitious web applications. Although pure MVC allows a developer to separate concerns, it does not provide you with all the tools and your application will need other constructs. Today, I'm going to talk about one of those constructs. Ember components are essentially sandboxed re-usable chunks of UI. If you are not familiar with Ember, please check out Getting Started With Ember.js or the Let's Learn Ember Course. In this tutorial, we will cover the Web Components specification, learn how to write a component in Ember, talk about composition, explain the difference between an Ember view and an Ember component, and practice integrating plugins with Ember components.Read More…
  • Code
    JavaScript & AJAX
    Working With IndexedDB - Part 3Indexeddb retina preview
    Welcome to the final part of my IndexedDB series. When I began this series my intent was to explain a technology that is not always the most... friendly one to work with. In fact, when I first tried working with IndexedDB, last year, my initial reaction was somewhat negative ("Somewhat negative" much like the Universe is "somewhat old."). It's been a long journey, but I finally feel somewhat comfortable working with IndexedDB and I respect what it allows. It is still a technology that can't be used everywhere (it sadly missed being added to iOS7), but I truly believe it is a technology folks can learn and make use of today. In this final article, we're going to demonstrate some additional concepts that build upon the "full" demo we built in the last article. To be clear, you must be caught up on the series or this entry will be difficult to follow, so you may also want to check out part one.Read More…
  • Code
    JavaScript & AJAX
    Working With IndexedDB - Part 2Indexeddb retina preview
    Welcome to the second part of my IndexedDB article. I strongly recommend reading the first article in this series, as I'll be assuming you are familiar with all the concepts covered so far. In this article, we're going to wrap up the CRUD aspects we didn't finish before (specifically updating and deleting content), and then demonstrate a real world application that we will use to demonstrate other concepts in the final article.Read More…