042 BackboneJS

12 May 2013

BackboneJS is a client-side MV* framework that will help us structure our code, provide templates to inject the data as well as render a fast changes UI with ajax. In this episode we will create a simple client-side reading list of computing books!

Download video: mp4

Sample code: Github

Version: 1.0.0

Similar episodes: 013 RequireJS, 034 Lodash

##Background on BackboneJS

  1. Main website
  2. Github
  3. Backbone Fundamental
  4. Ajax - New appraoch to web applications
  5. TodoMVC
  6. Sublime text pluging - backbone js snippets

##Things to learn with BackboneJS

###1. install

  1. BackboneJS has one hard dependancy, UnderscoreJS and we will also include jQuery for any DOM manipulation. Let’s first create the bare index.html file. Open the console in the browser and query for $ for jQuery, _ for underscore and Backbone for backbone.

    ``` <!doctype html>

    My Todo List

    ```

  2. create a simple class within the script tags without Backbone:

    ``` var Read = function(config) { this.author = config.author; this.cover = config.cover; };

    Read.prototype.display = function() { return this.title + ‘ by ‘ + this.author; };

    ```

    try them out in the console:

    var read = new Read({title: 'Code Complete', author: 'Steve McConnell'}); read.title; read.author; read.display();

##2. models

  1. create new model: delete the script contents and refer to <script src="js/models/read.js"></script> with the contents in file js/models/read.js
  2. start a new model:

    var app = app || {};
    
    app.Read = Backbone.Model.extend({
      // all function henceforth will be inside here
    });
    
    
  3. initialize

    initialize: function() { console.log('New book to read is added to the reading list!'); }

  4. custom function

    display: function() { return this.title + ' by ' + this.author; }

  5. on change

    ``` initialize: function() { … this.on(‘change:title’, function(model){ var title = model.get(‘title’); console.log(‘Happy reading ‘ + title + ‘ !’ ); });

    } ```

  6. defaults

    defaults: { cover: 'img/placeholder.png', title: 'No title', author: 'Unknown' }

    try them out in the browser console:

    ``` var read2 = new app.Read({title: ‘Mythical Man-Month’, author: ‘Frederick Brooks’});

    read2.get(‘title’); // ‘Mythical Man-Month’ read2.get(‘author’); // ‘Frederick Brooks’

    read2.set(‘title’, ‘Pragmatic Programmer’); read2.set(‘author’, ‘Andrew Hunt and David Thomas’);

    read2.get(‘title’); // “Pragmatic Programmer” read2.get(‘author’); // “Andrew Hunt and David Thomas” ```

  7. validate in file js/models/read.js

    ``` // after display function validate: function(attrs, options) { if (attrs.title === ‘’) { return ‘Title of the book cannot be blank’; } }

    ``` try in the browser console:

    ``` var read = new app.Read(); read.get(‘title’); // “No title”

    read.set(‘title’, ‘’, {validate: true}); // false read.get(‘title’); // “No title”

    read.set(‘title’, ‘Pragmatic Programmer’, {validate: true}); read.get(‘title’); // “Pragmatic Programmer”

    ```

  8. create a file js/app.js for all initializations and add <script src="js/app.js"></script> to file index.html:

    ``` var read1 = new app.Read({ title: ‘Mythical Man-Month’, author: ‘Frederick Brooks’ }), read2 = new app.Read({ title: ‘Pragmatic Programmer’, author: ‘Andrew Hunt and David Thomas’ });

    ```

##3. views and templates

  1. start a read view in file js/views/read.js:

    ``` var app = app || {};

    app.ReadView = Backbone.View.extend({ // book view }); ```

    try in the browser console:

    var readView = new app.ReadView() readView.el readView.$el // wrapped in jQuery

  2. tagName, className and id

    ``` var app = app || {};

    app.ReadView = Backbone.View.extend({ tagName: ‘li’, className: ‘book’, id: ‘book-element’ }); ``` try in the browser console:

    var readView = new app.ReadView() readView.el readView.$el // wrapped in jQuery readView.$el.removeClass() // jQuery functions can be used

  3. render, initilize and inline template

    ``` var app = app || {};

    app.ReadView = Backbone.View.extend({ tagName: ‘li’,

    template: _.template(“<%= title %> by <%= author %>”),

    initialize: function() { this.render(); },

    render: function() { this.$el.html( this.template(this.model.toJSON())); } }); ``` try in the browser console:

    var readView = new app.ReadView({model: read1}) readView.el

  4. external template

    in file js/views/read.js

    ``` var app = app || {};

    app.ReadView = Backbone.View.extend({ tagName: ‘li’,

    template: _.template( $( ‘#readView’ ).html() ), // NEW

    initialize: function() { this.render(); },

    render: function() { this.$el.html( this.template(this.model.toJSON())); return this; } });

    ``` in file index.html

    <script type="text/template" id="readView"> <%= title %> by <%= author %> </script> try in browser console:

    var readView = new app.ReadView({model: read1}) readView.el $(document.body).append(readView.el)

##4. collections

  1. start in file js/collections/reads.js

    ``` var app = app || {};

    app.Reads = Backbone.Collection.extend({ model: app.Read });

    ```

    include the new file in the script tag in file index.html:

    ... <script src="js/models/read.js"></script> <script src="js/collections/reads.js"></script> <!-- new --> <script src="js/app.js"></script> ...

    add to file js/app.js for all initializations:

    … var readings = new app.Reads([read1, read2]);

    try in the browser console:

    readings.length; // 2 readings.toJSON()

  2. initialize with add/remove/length in file js/collections/reads.js

    ``` initialize: function() {

     this.on('add', function(model){
       var title = model.get('title');
       console.log('New book added to the reading list: ' + title );
       console.log('Reading collection size: ' + this.length );
     });
    
     this.on('remove', function(model){
       var title = model.get('title');
       console.log('Book removed from the reading list: ' + title );
       console.log('Reading collection size: ' + this.length );
     });  }  ```  try in the browser console:
    

    readings.remove([read1]); readings.add([read1]);

##5. collection view

  1. in file index.html right after the <body>

    ```

    ```

  2. in file js/views/reads.js:

    ``` var app = app || {};

    app.ReadsView = Backbone.View.extend({

    el: ‘#reads’,

    initialize: function( initialReads ) { this.collection = new app.Reads( initialReads ); this.render(); this.listenTo( this.collection, ‘add’, this.renderRead ); },

    render: function() { this.collection.each(function( item ) { this.renderRead( item ); }, this ); },

    renderRead: function( item ) { var readView = new app.ReadView({ model: item }); this.$el.append( readView.render().el ); }

    }); ```

  3. in file js/app.js

    ``` var reads = [ { title: ‘Mythical Man-Month’, author: ‘Frederick Brooks’ }, { title: ‘Pragmatic Programmer’, author: ‘Andrew Hunt and David Thomas’ }, { title: ‘Code Complete’, author: ‘Steve McConnell’}, { title: ‘The Design of Everyday Things’, author: ‘Donald Norman’ } ];

    new app.ReadsView(reads);

    ```

###6. add button

  1. in file index.html add the following inside the <div> tags

    ```

</div> ``` 1. in file js/views/reads.js add:

```
events:{
  'click #add':'addRead'
},

addRead: function( e ) {
  e.preventDefault();

  var formData = {};

  $( '#addRead' ).children( 'input' ).each( function( i, el ) {
       formData[ el.id ] = $( el ).val();
  });

  this.collection.add( new app.Read( formData ) );
}
``` 1. try using the form to add the books

###7. delete button

  1. add in file index.html a done button:

    <script type="text/template" id="readView"> <%= title %> by <%= author %> <button id="done">Done</button> </script>

  2. add in file js/views/read.js:

    ``` events: { ‘click #done’: ‘doneReading’ },

    doneReading: function() { this.model.destroy(); this.remove(); } ```

  3. try to click the done buttons!

###8. improvements:

  1. add a server side
  2. connect to database
  3. templates
  4. add AMD script loader

##More Resources on BackboneJS 1. Backbone Tutorials 2. Backbone tutorials and screencasts 1. Journey through the JavaScript MVC Jungle 2. Rich JavaScript Applications – the Seven Frameworks 3. A Comparison of Angular, Backbone, CanJS and Ember

##Build Link of this episode

sidebar.io - best design links everyday!