DataTables TableTools Extension with AngularJS/RequireJS

We use a flexible jQuery plug-in called DataTables at my job to handle generating large display tables. One often-requested feature was the ability to download the table as a CSV file. DataTables has an extension called TableTools that I used to implement this feature. TableTools lets you copy the table to the clipboard, export to CSV, XLS, and PDF, and also gives a clean, large view suitable for printing. Getting TableTools to work w/ AngularJS was a bit challenging.

// Define as an AMD module if possible
if ( typeof define === 'function' && define.amd ) {
	define( ['jquery', 'datatables'], factory );
}
else if ( typeof exports === 'object' ) {
    // Node/CommonJS
    factory( require('jquery'), require('datatables') );
}
else if ( jQuery && !jQuery.fn.dataTable.TableTools ) {
    // Otherwise simply initialise as normal, stopping multiple evaluation
    factory( jQuery, jQuery.fn.dataTable );
}

^ This logic at the very end of dataTables.tableTools.js  was conflicting with RequireJS. Specifically, require.js was properly loading the DataTables file (jquery.dataTables.js), but the conditional block here was trying to load dataTables.js. A 404 error was being thrown. I only needed the very last branch of the if statement:

factory( jQuery, jQuery.fn.dataTable);

You can check if TableTools (or another extension) is being properly loaded by using the DataTables Debug Bookmarklet. The debug bookmarklet shows you what extensions are correctly installed: Screen Shot 2014-07-16 at 6.50.46 PMdownload it from here. Once TableTools is installed, you should be able to use it with code like this:

      # Set up the TableTools DataTables extension for CSV exporting
      _createTableTools = (myDataTable) ->
        tt = new $.fn.DataTable.TableTools( myDataTable,
          sSwfPath: "/path/to/TableTools/swf/copy_csv_xls.swf"
          aButtons: [ "csv" ]
        )

        $(tt.fnContainer()).insertBefore('div.dataTables_wrapper');

That’ll place a CSV download button right above an existing DataTable. I call this function after I create a table, passing in the DataTable instance as a parameter. Note that /path/to/TableTools/swf/copy_csv_xls.swf is from the site root, not the machine’s filesystem root. Note also that div.dataTables_wrapper is created by default when the DataTable is made–you don’t have to create that element yourself. You can also create the TableTools object as a property of the DataTable. Something like this should work:

        table = elem.find('table').dataTable(
          sDom: 'T<"clear">lfrtip'
          tableTools:
            sSwfPath: '/path/to/TableTools/swf/copy_csv_xls.swf'
          # Other table properties
          # ...
        )

Repositioning the buttons anywhere besides on the DataTable is…well…annoying. I think you have to first initialize the TableTools DOM element on the DataTable, and then remove it from its parent node and append it to another node. Even if you get the DOM element in the correct place, I found there were a few CSS gotchas. I won’t write about them here, as the changes a coworker and I made were specific to our layout. I had to change some of the default styles created within the ZeroClipboard_TableTools.Client.prototype section of dataTables.tableTools.js. If the buttons appear but aren’t working, ensure that the path to the SWF file is correct and that the actual SWF element in the DOM is in the correct space. When I moved the buttons from their default position, I found the SWF element was being absolutely positioned, which in this particular layout made it sit invisibly in the top left-hand corner of the browser window. When you’re done though, you’ll have export functionality sitting right alongside the DataTable. Screen Shot 2014-07-16 at 7.12.22 PM