Example of hidden rows of a DataTables table - the table title is inappropriate (a test case is attached)

I am trying to create a table where you can see more details when clicking on a plus image - similarly Example of hidden rows of a DataTables table

Unfortunately, a warning is displayed as a JavaScript warning, and the table title is also inappropriate - as if it had too many or not enough table cells:

enter image description here

I prepared a simple test case that will work instantly when you save it in a file and open it in a browser:

<!DOCTYPE HTML> <html> <head> <link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css"> <link type="text/css" rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script> <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script> <script type="text/javascript"> var data = [ {"Total":17,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":17,"Test":"GSM_1900_GMSK_TXPOWER_HP_H","Measurement":"MEASUREMENT"}, {"Total":8,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":8,"Test":"TX_PWR_64_54","Measurement":"POWER"} ]; $(function() { function fnFormatDetails(oTable, nTr) { var aData = oTable.fnGetData(nTr); var sOut = '<table bgcolor="yellow" cellpadding="8" border="0" style="padding-left:50px;">'; sOut += '<tr><td>BSN:</td><td>' + aData['Details']['BSN'] + '</td></tr>'; sOut += '<tr><td>Station:</td><td>' + aData['Details']['StationName'] + '</td></tr>'; sOut += '<tr><td>Project:</td><td>' + aData['Details']['ProjectName'] + '</td></tr>'; sOut += '</table>'; return sOut; } var fails = $('#fails').dataTable({ bJQueryUI: true, sPaginationType: 'full_numbers', aaData: data, aaSorting: [[2, 'desc']], aoColumns: [ { mDataProp: 'Test', bSearchable: true, bSortable: true }, { mDataProp: 'Measurement', bSearchable: true, bSortable: true }, { mDataProp: 'Total', bSearchable: false, bSortable: true }, { mDataProp: 'A', bSearchable: false, bSortable: true }, { mDataProp: 'B', bSearchable: false, bSortable: true }, { mDataProp: 'C', bSearchable: false, bSortable: true }, { mDataProp: 'D', bSearchable: false, bSortable: true }, ] }); var th = document.createElement('th'); var td = document.createElement('td'); td.innerHTML = '<img src="http://www.datatables.net/release-datatables/examples/examples_support/details_open.png" class="details">'; $('#fails tbody th').each(function() { this.insertBefore(th, this.childNodes[0]); }); $('#fails tbody tr').each(function() { this.insertBefore(td.cloneNode(true), this.childNodes[0]); }); $('#fails tbody').on('click', 'td img.details', function() { var nTr = $(this).parents('tr')[0]; if (fails.fnIsOpen(nTr)) { this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_open.png'; fails.fnClose(nTr); } else { this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_close.png'; fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details'); } }); }); </script> </head> <body> <table id="fails" cellspacing="0" cellpadding="4" width="100%"> <thead> <tr> <th>Test</th> <th>Measurement</th> <th>Total</th> <th>A</th> <th>B</th> <th>C</th> <th>D</th> </tr> </thead> <tbody> </tbody> </table> </body> </html> 

Anyone have an idea how to fix this?

I tried adding / removing <th>Details</th> in the body of the HTML, but that didn't help.

I also asked this question on the DataTables forum .

UPDATE:

I received useful comments from the author of DataTables and decided to simply add a plus image to the contents of the first cell in each row - instead of adding a new cell to each row.

Unfortunately, I had a new problem: a plus image is displayed, but there is no single text (test name):

enter image description here

Here is my new code (plus image added by propTest ):

 <!DOCTYPE HTML> <html> <head> <link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css"> <link type="text/css" rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script> <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script> <script type="text/javascript"> var data = [ {"Total":17,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":17,"Test":"GSM_1900_GMSK_TXPOWER_HP_H","Measurement":"MEASUREMENT"}, {"Total":8,"A":0,"B":0,"Details":{"BSN":"1147387861","ProjectName":"R127","StationName":"D"},"C":0,"D":8,"Test":"TX_PWR_64_54","Measurement":"POWER"} ]; function propTest(data, type, val) { if (type === 'set') { console.log(val); // for some reason prints "null" data.name = val; data.display = '<img src="http://www.datatables.net/release-datatables/examples/examples_support/details_open.png" width="20" height="20" class="details"> ' + val; return; } if (type === 'display') { return data.display; } // 'sort', 'type', 'filter' and undefined return data.name; } $(function() { function fnFormatDetails(oTable, nTr) { var aData = oTable.fnGetData(nTr); var sOut = '<table bgcolor="yellow" cellpadding="8" border="0" style="padding-left:50px;">'; sOut += '<tr><td>BSN:</td><td>' + aData['Details']['BSN'] + '</td></tr>'; sOut += '<tr><td>Station:</td><td>' + aData['Details']['StationName'] + '</td></tr>'; sOut += '<tr><td>Project:</td><td>' + aData['Details']['ProjectName'] + '</td></tr>'; sOut += '</table>'; return sOut; } var fails = $('#fails').dataTable({ bJQueryUI: true, sPaginationType: 'full_numbers', aaData: data, aaSorting: [[2, 'desc']], aoColumns: [ { mData: propTest, bSearchable: true, bSortable: true }, { mData: 'Measurement', bSearchable: true, bSortable: true }, { mData: 'Total', bSearchable: false, bSortable: true }, { mData: 'A', bSearchable: false, bSortable: true }, { mData: 'B', bSearchable: false, bSortable: true }, { mData: 'C', bSearchable: false, bSortable: true }, { mData: 'D', bSearchable: false, bSortable: true } ] }); $('#fails tbody').on('click', 'td img.details', function() { var nTr = $(this).parents('tr')[0]; if (fails.fnIsOpen(nTr)) { this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_open.png'; fails.fnClose(nTr); } else { this.src = 'http://www.datatables.net/release-datatables/examples/examples_support/details_close.png'; fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details'); } }); }); </script> </head> <body> <table id="fails" cellspacing="0" cellpadding="4" width="100%"> <thead> <tr> <th>Test</th> <th>Measurement</th> <th>Total</th> <th>A</th> <th>B</th> <th>C</th> <th>D</th> </tr> </thead> <tbody> </tbody> </table> </body> </html> 
+7
html css html-table datatables
source share
1 answer

There are several ways to achieve this type of behavior using DataTables (DT). You can achieve your original goal or use the same column for the expander and Test data.

I use the time to show several options, as I hope this can serve as a reference to others who are asked to do something similar.

For everyone below, your table should contain all the columns you need before creating the DT (statically or dynamically).


Expander in a separate column

Using the default content property:

This is an option that requires minimal modification to your existing example and is probably the easiest. Just add the sDefaultContent parameter for your extra column:

 { mData: null, bSearchable: false, bSortable: false, sDefaultContent: '<div class="expand /">', sWidth: "30px" }, 

The mData mData set to null , because its contents have nothing to do with the row data array. This forces DT to use the value in sDefaultContent .

I took the liberty of using CSS for the extension button, as this simplifies the example and also separates behavior and presentation.

CSS I use:

 tr div.expand { width: 20px; height: 20px; background-image: url('http://www.datatables.net/release-datatables/examples/examples_support/details_open.png'); } tr div.open { background-image: url('http://www.datatables.net/release-datatables/examples/examples_support/details_close.png'); } 

and expander functions:

 $('#fails tbody').on('click', 'td div.expand', function () { var nTr = $(this).parents('tr')[0]; if (fails.fnIsOpen(nTr)) { $(this).removeClass('open'); fails.fnClose(nTr); } else {$.fn.dataTableExt.sErrMode = 'throw' ; $(this).addClass('open'); fails.fnOpen(nTr, fnFormatDetails(fails, nTr), 'details'); } }); 

We aim a div on the expand class and switch its open class as needed.

Separate expand column

JSBin example .


Extender contained in the first column

Using Formatter:

You can specify the aoColumnDefs configuration array, which is more powerful and flexible than config aoColumns .

The rendering function for this column is mRender using the mRender configuration mRender .

Corresponding column settings:

 aoColumnDefs: [{ aTargets: [0], mData: 'Test', bSearchable: true, bSortable: true, mRender: expandRenderer }, ... ] 

This function is called several times in different contexts and should tell DT how to display the data in the table itself, and also help determine the data type for sorting and filtering.

Renderer:

 function expandRenderer(data, type, full) { switch (type) { case 'display': return '<div class="expand-wrapper">'+ '<span class="expand"></span>'+ '<span class="data">'+ data+ '</span></div>'; case 'type': case 'filter': case 'sort': return data; } } 

3 arguments required:

  • data : data from an array of strings, in this case the string stored in Test .
  • type : type of request. This means that DT expects to return:
    • 'display' : what will be displayed in the cell itself.
    • 'type' : what is returned from the function will be used to determine the data type of the string.
    • 'filter' , 'sort' : data that will be used when filtering (searching) and sorting the table.
  • full : full data for this row.

This time I decided to use a span wrapped in a div . To center the icon vertically and keep the table on one line, I used the following CSS:

 tr span.expand { width: 20px; height: 20px; background-image: url('http://.../details_open.png'); display:inline-block; vertical-align: middle; margin-right: 5px; } div.expand-wrapper { white-space:nowrap; } 

vertical-align: middle works as intended, as it is an inline display ( inline-block in particular).

Without this, CSS DT will not handle column widths gracefully, since the first column is not aware of the increase in space that the expander makes.

Without this CSS: Expander in same column

Using this CSS:

Expander in same column and same line

And the corresponding example is JSBin .

Tip:

I don't like using alert() to display errors. For DT, you can change this behavior by changing the error mode setting:

 $.fn.dataTableExt.sErrMode = 'throw' ; 

This will throw an exception, so you can catch its JIT using your console or register it if it fails.

Resources:

Parameters of the DataTable column .

Quick access to DataTable data .


PS

Further customization can be done by passing the function as the mData configuration mData , but this is beyond the scope of this answer.

+8
source share

All Articles