Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to better define JQuery DataTables column rendering?

We use JQuery DataTables extensively. I am now switching all the app tables to AJAX data source to better support search and to render tables faster.

The problem I am having is how to define data rendering inside my table columns. I do not render only data in the column but I need to have some additional markup in some columns (like <span class="label">data</span> or links, etc.).

This can be done via javascript, here is how I did it. The problem is I don't want to have this column definition syntax for every table in my app. Not two tables are identical, and to support all tables/columns like this it would result in bunch of javascript code for every table. I don't see this as a good practice.

$('.data-table').each(function(){
    initialize_ajax_data_tables($(this));
});

function initialize_ajax_data_tables(element)
{
    var display_rows = element.attr('data-rows') ? parseInt(element.data('rows')) : 25;
    var initial_sort = element.attr('data-sort') ? element.data('sort') : [0, 'asc'];

    dataTables = element.DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {
            url: base_url+'ajaxprocess/products_data_table.json',
            type: 'GET'
        },
        "columns": [
           { "data": "id" },
           { "data": "product_type_name" },
           { "data": "code" },
           { "data": "name" },
       ],
       "columnDefs": [
           {
               "render": function ( data, type, row ) { 
                   return '<span class=\"label label-info\">'+ data +'</span>'; 
               },
               "targets": 1
           },
           {
               "render": function ( data, type, row ) { 
                   return '<span class=\"label label-success\">'+ data +'</span>';
               },
               "targets": 2
           },
       ],
        "pageLength": display_rows,
        "order": initial_sort,
    });
    dataTables = $.fn.dataTable.fnTables(true);
}

Is there a way to somehow define this column definition/rendering in HTML itself and then pull this in the javascript when initialising DataTables? Or any other way on how to approach this issue?

For sorting rules and pageLength on the DataTables I use data-attributes from the <table> element and that works perfect. This way I define attributes like:

<table id="DataTables_Table_0" class="data-table" data-rows="50" data-sort="[0,&quot;desc&quot;]">

This works fine, but can not use this for columnDefs arrays as render attribute expects function.

like image 686
Primoz Rome Avatar asked Sep 15 '15 08:09

Primoz Rome


1 Answers

I am making some progress and am posting my findings bellow. Maybe some find this useful, but I would still be open to other solutions in case you have a better design.

Currently I have split my code into two three sections:

  1. Main application JS file: common DataTables initialisation code for all the application tables
  2. View: HTML table view generated by the backend and served to the browser. In this view I define table specific properties which are then referenced in in common DataTable init code
  3. Backend AJAX script which serves table data

So to demonstrate this with actual code.

1. Main initialisation code

$('.data-table').each(function(){
    initialize_data_tables($(this));
});
function initialize_data_tables(element)
{
    if(!(element instanceof jQuery)) element = $(element);
    var table_defs = element.attr('data-table-def') ? eval(element.data('table-def')) : [];
    dataTables = element.DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {
            url: table_defs.url,
            type: 'POST'
        },
        "columns": table_defs.columns,
        "pageLength": table_defs.rows,
        "order": table_defs.sort,
    });
    dataTables = $.fn.dataTable.fnTables(true);
}

2. The HTML view Here I define specific JS object for table definition, column definition and so on. Every table in app has specific definition. This structure also allows me to have multiple data tables on the view at the same time and reference the right JS object with table properties definition.

<script type="text/javascript">
        var tableDef = {
            url: "<?= Uri::create('utilities/ajaxprocess/products_data_table.json') ?>",
            columns: [
                    { "data": "id" },
                    { "data": "product_type_name", render: function ( data, type, row ) { 
                           return '<span class=\"label label-info\">'+ data +'</span>'; 
                       } 
                    },
                    { "data": "code" },
                    { "data": "name" },
                ],
            rows: 50,
            sort: [ 0, 'desc' ]
        };
</script>

<table class="data-table" data-table-def="tableDef”>...</table>

3. The backend No need to paste my code here. Just functions that query my database and prepare data to be served via AJAX to DataTables.

like image 74
Primoz Rome Avatar answered Oct 09 '22 03:10

Primoz Rome