Changing Some DataTables Settings on the Fly, Or At Least Pretending We Did


I'm a big fan of the dataTables jQuery plug-in. It takes your tables of data and adds all the sorts of goodies that all the sorts that clients adore, like pagination, filtration, column sorting, and pretty styling with minimal fuss and code. It can read from a variety of data sources as well, so for our larger tables with hundreds or thousands of records, it can hand off some of the processing to the database instead. Love it!

As I'm sure many of you have encountered, though, you may not always want a table to have pagination, filtration, etc if it has a relatively small record set. If you know it will always have small numbers, usually for us fewer than 20 records, you can easily turn those options off when you call dataTables. But what about when you don't know, i.e. the table contents are dynamic based on a query?

Our usual solution in such a case was to wrap some of the calling code with ColdFusion CFIFs to change up the settings based on the record count. Kind of like this:

$(".listTable").dataTable({
    "bStateSave": false,
    "bAutoWidth": true,
    "bJQueryUI": true,
    <cfif qMyQuery.RecordCount GT 25>
        "iDisplayLength": 25,
        "sPaginationType": "full_numbers",
   <cfelse>
        "bFilter": false,
        "bInfo": false,
        "bLengthChange": false,
        "bPaginate": false,
    </cfif>
    ]
});

It isn't "pretty" but hey, it worked. Still, it wasn't very elegant and we really hate having to put CFML in our JavaScript area. Recently it bugged me enough to start exploring other options. Now, I already knew that the one drawback/flaw in the current version of dataTables is that the API will not let you change the table's settings on the fly or after the table is rendered. So that method wasn't an option. Nor does it have a built in mechanism for "if less than X records, show the whole table and remove options" (which would be a nice plug-in for dataTables, for better gurus than me).

After cursing Google's asinine preference to push old forum postings above newer ones in their search listings, I found posts from a few folks wanting to do the same, but they were all for significantly older versions of dataTables so the ideas mentioned didn't work anymore. Still, they gave me a starting point, the fnInitComplete() callback. After a bit of trial and error, here is what I came up with:

$(".listTable").dataTable({
    "bStateSave": false,
    "bAutoWidth": true,
    "iDisplayLength": 25,
    "sPaginationType": "full_numbers",
    "bJQueryUI": true,
    "fnInitComplete": function() {
        /* auto change settings if it has fewer than 25 rows */
        var oListSettings = this.fnSettings();
        var wrapper = this.parent();
        
        if (oListSettings.fnRecordsTotal() < 25) {
            $('.dataTables_paginate', wrapper).hide();
            $('.dataTables_filter', wrapper).hide();
            $('.dataTables_info', wrapper).hide();
            $('.dataTables_length', wrapper).hide();
        }
    }
});

You can easily adjust this, of course, to only remove the particular functions you want to remove for low records and to change the threshold for what is considered "low". It doesn't really change the settings on the fly, but by hiding those elements, it makes it look like we did.  I should also note, I did some some remarks that hinted that using hide() like I did may cause issues with table layout. Since all of the dataTables instances I am using it on also utilize my UI templates for style, I haven't seen any issue. I haven't tried it with a non-UI styled table though.

This probably isn't ground breaking for dataTables guru and I imagine someone will come along with an even cleaner solution, but this one is working for us pretty well and no CF code in our JS 🙂