Introduction to Backbone.js – To-do List

Backbone.js is a great framework for medium and large scale Javascript applications. It provides a flexible foundation  that allows for extensions and adaptation. It has a good name and is used on a lot of high profile projects, such as “Basecamp Mobile,” ”SoundCloud Mobile” and “Groupon Now!“. To-do lists seem like a popular example, and for good reason: it’s good way to expose the different elements of this framework. So why not try to make a to-do list from scratch? Four hours later, I had something acceptable.

Click here for the full demo.

ToDo Model

The first thing to do was to create the atomic model for a to-do item. The to-do item should  have a title and a completed state (true if completed, false if not).

/*
 * Set up to-do model
 */
ToDo = Backbone.Model.extend({
     //define model default values
     defaults: {
          title: "To Do",
          completed: false
     }
});

//create a dumy to do item
var toDo = new ToDo({
     //override model default values
     title: "False"
});

Already, I can see advantages over using raw Prototype objects. The syntax is succinct, which is always a good thing. A terse syntax is easier to learn and easier to read, and exposes errors more readily than a verbose one. Secondly, constructor definition isn’t required; there is a standard constructor that handles basic operations that don’t need to be recreated. Finally, model constructor takes in an object to override default values. Anyone familiar with jQuery plugins can appreciate the utility of this method; it obviates the necessity of passing multiple parameters to a constructor.

ToDoList Model

Before I move on to the List model, I created a ToDo Collection. A Collection is another Class in Backbone that can be seen as a rich array containing objects of a Model type. In this case, I created a collection to hold ToDos.

/*
 * Collection of ToDos Models
 */
ToDoCollection = Backbone.Collection.extend({
     model: ToDo //only accept ToDos
});

Easy. Now on to the ToDoListModel definitions. In this case, a ToDoList will have a title and a ToDoCollection. It will also have an instance method for adding a ToDo to the list.

/*
 * Model for the ToDo List
 */
ToDoList = Backbone.Model.extend({
     defaults:{
          toDos: new ToDoCollection(),
          title: "Untitled"
     },
     addToDo: function(toDo){
          this.get("toDos").add(toDo); //reference toDos collection and add the new toDo
     }
});

This brings up one of the few things I don’t like about Backbone: attributes of a model are accessed by passing a string to the get function (see line 10 above). However, this is unavoidable when considering a crucial feature of Backbone that I will be covering later.

Views

Views in Backbone are a lot like ViewControllers in UIKit. They reference the html element the view is tied to, and handle event from the element and its descendants. Additionally, the view can be tied to a specific model, which can be very useful. Below is a skeleton Backbone view.

The views used in the ToDo List are much longer than needed for exposition. The final implementation can be seenhere.

ToDoView

ToDoView = Backbone.View.extend({
     initialize: function(){
          //do stuff with the model if you want
          this.model; //reference to the views model

          this.render();
     },
     render: function(){
          //create and fill in the view
          this.el; //reference to the html element
          this.$el; //reference to the jQuery object for this view
     },
     //object containing events and listeners
     events{
          "click a" : "doLinkClick"
     },
     //click listener
     doLinkClick: function(){
          //respond to click
     }
});

var v = new ToDoView({
     el: document.getElementByID("element_id"), //this can also be a jQuery object,
     model: new ToDo() // start the skeleton view with a model
});

Binding to model events

A useful feature of Backbone (one that it shares with Knockout.js), is the ability to bind events to the attributes of a model. For example, when the value of an attribute is changed, an event is fired. The view can then bind listeners to these events.

ToDoView= Backbone.View.extend({
     initialize: function(){
              var t = this;
              this.model.bind("change:title", function(){
                   t.onToDoTitleChange();
               });
     },
     onToDoTitleChange: function(){
          //do stuff on title change
     }
});

Briefly On Templates

The concept of templates is implemented by at least a couple of javascript frameworks. Templates are not a feature of Backbone, but rather one of its dependencies (Underscore.js). Regardless, templates are very helpful.

For templates, you simply load a template of html and define places where attributes of the model are inserted into the markup.

<script type="text/javascript">
SkelletonView = Backbone.View.extend({
     initialize: function(){
          //get elem from template
          var processedTempated = _.template(this.$el.html(), this.model.toJSON());
          //set element to the process template
          this.setElement($(processedTempated));
     }
});

var v = new ToDoView({
     el: document.getElementByID("toDoTemplate"), //this can also be a jQuery object,
     model: new ToDo() // start the skeleton view with a  model
})
</script>

<script id="toDoTemplate" type="text/html">
	<li><%= title ></li>

</script>

In this case the template generator inserts the model’s title into the list element markup as text. Attributes can also be inserted anywhere in the markup. Templates are awesome.

Conclusion

Backbone addresses a lot of issues that can arise in large javascript applications. The simplified MCV, event handling, and templating (through Underscore.js) aid common tasks. I will be delving further into this framework in the future.

via C0d3!t

LEAVE A COMMENT