DataTables logo DataTables

via Ad Packs
How to split record across multiple rows
  • Hi all. I have records that contain a "notes" field. I want all of the fields except the notes field to appear on one row and I want the notes to show up on a second row. The notes field does not require a header. I have looked at the examples but could not figure out how to achieve my goal from them.

    Thank you for any help that can be provided.
    Doug
  • Hi Doug,

    Do you mean something like this: http://datatables.net/examples/api/row_details.html ? If not, could you elaborate a little please?

    Thanks!
    Allan
  • Your example does include fields from the current record on a second row but my second row would not need to be hidden and so I was thinking I would need to combine some of this examples code with the Rowcallback function?

    Does this sound right?
  • Hi Doug,

    Ah okay - so basically you just want the details row from my example to be "open" all the time? You could just to that then - when the initialisation of the table is complete, just call fnOpen() for all of the tr nodes in the table (the open rows are retained over paging/filtering etc - unless you are using server-side processing...). This way you wouldn't need to worry about the rows being "attached" to a parent etc.

    Does that sound like it work work for you?

    Regards,
    Allan
  • It sounds like it would but, I do not know how to call fnOpen() for all of the tr nodes in the table.
  • my code as it is now renders but only shows the detail row at the very bottom of the table as opposed for each row.
    var oTable;
    
    /* Formating function for row details */
    function fnFormatDetails ( nTr )
    {
    	var iIndex = oTable.fnGetPosition( nTr );
    	var aData = oTable.fnSettings().aoData[iIndex]._aData;
    			
    	var sOut = '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">';
    	sOut += '<tr><td>Rendering engine:</td><td>'+aData[1]+' '+aData[4]+'</td></tr>';
    	sOut += '<tr><td>Link to source:</td><td>Could provide a link here</td></tr>';
    	sOut += '<tr><td>Extra info:</td><td>And any further details here (images etc)</td></tr>';
    	sOut += '</table>';
    			
    	return sOut;
    }
    
    $(document).ready(function() {
    			
    	/*
    	 * Initialse DataTables, with no sorting on the 'details' column
    	 */
    	oTable = $('#aircraft').dataTable( {
    		"bPaginate": false,
    		"iDisplayLength": 500,
    		"bLengthChange": false,
    		"bProcessing": true,
    		"bFilter": true,
    		"bInfo": true,
    		"bAutoWidth": false,
    		"sDom": 'rtip',
    		"aoColumns": [
    			{ "sWidth": '30px' },
    			{ "sWidth": '40px' },
    			{ "sWidth": '30px' },
    			{ "sType": 'block-custom', "sWidth": '30px' },
    			{ "sWidth": '30px' },
    			{ "sWidth": '120px' },
    			{ "sWidth": '60px' },
    			{ "sWidth": '60px' },
    			{ "sWidth": '60px' },
    			null
    		] } );	
    		
    	$(oTable.fnGetNodes()).each( function () {
    		oTable.fnOpen( this, fnFormatDetails(this) );
    	} );
    	
            });
    
  • Hi Doug,

    I've just experimented with this a little bit, and it's actually a little more complicated than I had thought... DataTables (at the moment) requires that a row be 'visible' (i.e. on the page) before it can be opened - which is, I suspect, where you are running into issues.

    So two ways around this. The first is to edit the fnOpen function to wrap the 'insertAfter' line like so:

    /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
    var nTrs = $('tbody tr', oSettings.nTable);
    if ( $.inArray(nTr, nTrs) != -1 )
    {
    	$(nNewRow).insertAfter(nTr);
    }
    
    Which I will include in the next release of DataTables. With this - your current code should work as is.

    That is probably the better option - but another one is to use fnDrawCallback to open any rows which aren't already open on display:

    oTable = $('#example').dataTable( {
    	"fnDrawCallback": function () {
    		/* Open rows for all pages - after initialisation */
    		if ( typeof oTable != 'undefined' ) {
    			$('#example tbody tr:not(.details)').each( function () {
    				oTable.fnOpen( this, fnFormatDetails(this), 'details' );
    			} )
    		}
    	}
    });
    
    /* Open rows for the first page */
    $('#example tbody tr').each( function () {
    	oTable.fnOpen( this, fnFormatDetails(this), 'details' );
    } )
    

    Regards,
    Allan
  • I tried both methods mentioned above and neither worked. The result is the same as before which is that the detail row only shows for the last row of the table. Any ideas? I'm lost.
  • Update: I checked to see what version of datatables I was using and it was 1.4 beta 5. Wow!! Old version. I updated to 1.5.2 and it is now adding the detail for each row. The highlighting is not right however.

    Row 1 - Highlighted
    Row 1 detail - no highlight

    Row 2 - No highlight
    Row 2 detail - no highlight

    pattern repeats
  • What I was expecting is

    Row 1 - Highlighted
    Row 1 detail - Highlighted

    Row 2 - No highlight
    Row 2 detail - No highlight

    Row 3 begins repeat highlighting as Row 1

    Thanks
  • Hi Doug,

    Do you mean "highlighted" as in tr:hover? If so, you'll need to bare in mind that the detail row is actually a separate tr element, and as such it's highlighting will be separate from the "parent" (it's not really a parent in the DOM). To overcome this, you'll need to an an event handler to the tr elements. Something like - if it's a regular table row, add a class to the "child" row to highlight it. If it's a "child" row, add a class to the "parent" row to highlight it.

    Regards,
    Allan
  • Actually just was hoping to have the detail row have the same highlighting as the row above it. Is that a little more clear?

    Current:
    Row 1 = blue
    Row 1 detail = Grey
    Row 2 = white
    Row 2 detail = Grey

    Goal:
    Row 1 = blue
    Row 1 detail = blue
    Row 2 = white
    Row 2 detail = white

    Thanks
    Doug
  • Oh I see - you mean like the zebra striping? In that case you can just set the class name for the details rows, based on the parent on each draw (it has to be on each draw, and sorting and filtering can change the order). So just loop over all the TRs in the table (increment by 2 - i.e. one for the table row, and one for the detail row) and set the classes are required.

    Allan
  • Can you provide any example code?

    Thanks
    Doug
  • Here is a very quick piece of code. I've not tested it, and it could be seriously optimised - but perhaps it will show you the general idea. I wouldn't copy it line for line, particularly the getElementsByTagName, but it's a start :-)

    var nTrs = document.getElementsByTagName('tr');
    for ( var i=0, iLen=nTrs.length ; i<iLen ; i+=2 )
    {
    	if ( nTrs[i].className.match(/odd/) ) {
    		$(nTrs[i+1]).removeClass("odd even").addClass('odd');
    	} else {
    		$(nTrs[i+1]).removeClass("odd even").addClass('even');
    	}
    }
    
    Allan
  • Thanks Allan! I'll work with it and see what I can come up with.
This discussion has been closed.
All Discussions