Backbone.js Template: API-Driven Data Tables

Here’s a gist combining Backbone.js views and routes with API-driven tables from datatables.net. HTML not included, but it should be fairly obvious what’s going on here… a simple app for browsing auction listings.

… Enjoy!


/*
 * Template backbone.js code that encapsulates a 
 * datatable.net table within a view for a hypothetical ;)
 * auction listings application.
 */
 
var HomeRouter = Backbone.Router.extend({
  
  routes: {
    'refresh'     : 'refresh',   
    'newest'      : 'newest', 
    'endingsoon'  : 'endingsoon',
    'recentsold'  : 'recentsold', 
  },
    
});


var HomeView = Backbone.View.extend({
  
  // our default table view
  'present' : 'newest',
  
  'router' : new HomeRouter(),
  
  'events': {
    
    // users can enter a keyword,
    // but the table will only refresh after
    // the user can laid off the keys for 500ms
    'keyup #searchbox': _.debounce(function() {
      this.refresh();   
    }, 500 /* ms delay until taking real action */),
    
  },
  
  'newest': function() {
    this.present = 'newest';
    this.refresh();
  },
  
  'endingsoon': function() {
    this.present = 'endingsoon';
    this.refresh();   
  },
  
  'recentsold': function() {    
    this.present = 'recentsold';
    this.refresh();       
  },
  
  'refresh': function() {
    this.table.fnReloadAjax();    
  },

  
  'initialize': function() {
    
    var view = this;
    
    // setup routes
    //
    view.router.on('route:refresh', function() {      
      view.refresh();     
    });
    view.router.on('route:newest', function() {     
      view.newest();      
    });
    view.router.on('route:endingsoon', function() {     
      view.endingsoon();      
    });
    view.router.on('route:recentsold', function() {     
      view.recentsold();      
    });

    // setup table
    //
    view.table = $('#example').dataTable({
      "bProcessing": true,
      "bServerSide": true,
      "sAjaxSource": "/api/data",
  
      // override this, we supply our own keyword inputbox
      "sDom"       : 'p<"#toolbar">rtp',
  
      "aoColumns": [

        /* table declarations */

      ],
      
      "fnServerParams": function (aoData) {
        // before sending the request for data
        // we'll add our custom parameters for 'present' and 'keyword'
        if (view.present) {
          aoData.push( { "name": "present", "value": view.present } );
        }
        aoData.push( { "name": "keyword", "value": $('#searchbox').val() } );
      },      
    });   
  },  
});

/**
 * reload ajax plugin - available at http://datatables.net/plug-ins/api#fnReloadAjax
 */
$.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
{

  if ( typeof sNewSource != 'undefined' && sNewSource != null ) {
    oSettings.sAjaxSource = sNewSource;
  }
 
  // Server-side processing should just call fnDraw
  if ( oSettings.oFeatures.bServerSide ) {
    this.fnDraw();
    return;
  }
 
  this.oApi._fnProcessingDisplay( oSettings, true );
  var that = this;
  var iStart = oSettings._iDisplayStart;
  var aData = [];
  
  this.oApi._fnServerParams( oSettings, aData );
    
  oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aData, function(json) {
    /* Clear the old information from the table */
    that.oApi._fnClearTable( oSettings );
      
    /* Got the data - add it to the table */
    var aData =  (oSettings.sAjaxDataProp !== "") ?
      that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;
      
    for ( var i=0 ; i<aData.length ; i++ )
    {
      that.oApi._fnAddData( oSettings, aData[i] );
    }
      
    oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
      
    if ( typeof bStandingRedraw != 'undefined' && bStandingRedraw === true )
    {
      oSettings._iDisplayStart = iStart;
      that.fnDraw( false );
    }
    else
    {
      that.fnDraw();
    }
      
    that.oApi._fnProcessingDisplay( oSettings, false );
      
    /* Callback user function - for event handlers etc */
    if ( typeof fnCallback == 'function' && fnCallback != null )
    {
      fnCallback( oSettings );
    }
  }, oSettings );
};

/*
 * create the app view and start the browser history
 */
$(document).ready(function() {
    
  // app view
  new HomeView({el: $('body')});
  
  // get this party started
  Backbone.history.start();

} );

Leave a Reply