Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery datatables not able to select rows after redraw

I am using jquery datatable plugin to display a table in jquery UI dialog. Below is the function I am calling to draw the table.

function listPtCharges(filter){
var chgTable;
chgTable =
  $('#chargeTable').dataTable({
    "bJQueryUI": true,
    "bDestroy": true,    
    "sDom": 'tT',
    "bSort": false,
    "bAutoWidth": false,
    "sAjaxSource": "/ajax/ptchglist.php",
    "sAjaxDataProp": "Records",
    "fnServerData": function ( sSource, aoData, fnCallback ) {
      aoData.push( { "name": "acctno", "value": $("#curAcctno").val() } );
      aoData.push( { "name": "ins_id", "value": $("#ins_id").val() } );
      aoData.push( { "name": "filter", "value": filter } );
      $.ajax( {
        "dataType" : 'json',
        "type" : "POST",
        "url" : sSource,
        "data" : aoData,
        "success" : fnCallback
        } );
    } ,
    "aoColumns":
    [
     {"bVisible":false},
     {"sWidth": 55},
     {"sWidth": 30},
     {"sWidth": 40},
     {"sWidth": 125},
     {"sWidth": 50},
     {"sWidth": 50},
     {"sWidth": 20},                
     {"bVisible":false}  // allowed
    ],
    "oTableTools": {
      "sRowSelect": chgSelctionTyp,
      "sSwfPath": "/swf/copy_csv_xls_pdf.swf",
      "aButtons": []
    }
  });
}

This function is called just after the call to open dialog. Here are the lines of code that open the dialog and then load the table.

var oTT = TableTools.fnGetInstance( 'chargeTable' );
      if(oTT)
        oTT.fnSelectNone();
      $( "#chargeList" ).dialog( "open" );
      listPtCharges();

Within the dialog I have another button, with event handler to the value of filter and call the same function, with new filter. Newly loaded table always brings more number of rows from server.

Everything is fine except for a strange problem. Whenever a new table with more rows is drawn only the number of rows equal to previous table are selectable.

I mean suppose I loaded table with 5 rows, presssed button to bring new data set for table. Table got loaded with 8 rows. But now I will be able to select only top 5 rows. Rest all will result in error on firebug related to unidentified postion.

Any help in this regard is greatly appreciable.

EDIT: Here is the code that is trying to access the selected row.

    var oTT = TableTools.fnGetInstance( 'chargeTable' );
    var aData = oTT.fnGetSelectedData();

Also this is the part of jquery datatables which shows error in firebug.

"fnIsSelected": function ( n )
{
var pos = this.s.dt.oInstance.fnGetPosition( n );
return (this.s.dt.aoData[pos]._DTTT_selected===true) ? true : false;
}, 

Following error is displayed just after clicking the non-clickable rows.

TypeError: this.s.dt.aoData[pos] is undefined

I guess length of aodata is somehow still same as table loaded earlier.

like image 859
bvnbhati Avatar asked Jan 23 '13 13:01

bvnbhati


3 Answers

You shouldn't destroy and rebuild your table, you should just have datatable refetch the data.

I think calling fnDraw is enough to trigger the refresh - haven't tested though :

 $('#chargeTable').dataTable().fnDraw();

in your fnServerData function, you may need to change the way to load the filter parameter :

// keep this variable in some shared scope :
var filterPtr = {value: ''};

$('#chargeTable').dataTable({
    ....
    "fnServerData": function(...){
         ...
         aoData.push({ "name": "filter", "value": filterPtr.value });
         ...
     }
});

// if you need to update the filter :
filterPtr.value = 'newValue';
$('#chargeTable').dataTable().fnDraw();
like image 133
LeGEC Avatar answered Nov 15 '22 05:11

LeGEC


I mean suppose I loaded table with 5 rows, presssed button to bring new data set for table. Table got loaded with 8 rows. But now I will be able to select only top 5 rows. Rest all will result in error on firebug related to unidentified postion.

So the problem is that after clicking this button it might bring back more rows. It looks like this button is a filter, which may or may not include new rows.

It sounds like you need to re-initialize the datatable after modifying it. I've ran into issues when injecting new rows into a datatable after it has been initialized, and that is the only thing I was able to do to fix it.

I know this seems like overkill, but this is what has worked for me in the past. Calling redraw or setting the bDestroy flag just hasn't worked for me in this case.

Prior to injecting the new rows..

  1. Destroy table
  2. Inject rows
  3. Re-initialize datatable

Once again, this may or may not work for you, but it is what I've had to do in the past.

$('#filterButton').click(function()
{
  //revert table to it's original state
  $('#chargeTable').dataTable().fnDestroy();

  //do some stuff, inject rows and get new filter value
  var filter = 'new filter value';

  //re-initialize the datatable
  listPtCharges(filter);
});

function listPtCharges(filter){
var chgTable;
chgTable =
  $('#chargeTable').dataTable({
    "bJQueryUI": true,
    "bDestroy": true,    
    "sDom": 'tT',
    "bSort": false,
    "bAutoWidth": false,
    "sAjaxSource": "/ajax/ptchglist.php",
    "sAjaxDataProp": "Records",
    "fnServerData": function ( sSource, aoData, fnCallback ) {
      aoData.push( { "name": "acctno", "value": $("#curAcctno").val() } );
      aoData.push( { "name": "ins_id", "value": $("#ins_id").val() } );
      aoData.push( { "name": "filter", "value": filter } );
      $.ajax( {
        "dataType" : 'json',
        "type" : "POST",
        "url" : sSource,
        "data" : aoData,
        "success" : fnCallback
        } );
    } ,
    "aoColumns":
    [
     {"bVisible":false},
     {"sWidth": 55},
     {"sWidth": 30},
     {"sWidth": 40},
     {"sWidth": 125},
     {"sWidth": 50},
     {"sWidth": 50},
     {"sWidth": 20},                
     {"bVisible":false}  // allowed
    ],
    "oTableTools": {
      "sRowSelect": chgSelctionTyp,
      "sSwfPath": "/swf/copy_csv_xls_pdf.swf",
      "aButtons": []
    }
  });
}
like image 24
Kevin Avatar answered Nov 15 '22 04:11

Kevin


Tested and working!

Live Demo: http://jsfiddle.net/oscarj24/c9m3s/


I just tried to replicate the issue by creating a datatable and then add some extra hardcoded data with a click event using a button.

At first, everything was working fine but when adding extra rows, the previous ones were still able to select but the new ones were impossible and no error was present at browser console.

However, I'll suggest the following that might help you to "solve" the problem:

1.- Add the event handler for "selecting rows" after datatable initialization because rows will be already loaded in DOM.

2.- Instead of using .click(), .on('click') or .live('click') for "selecting rows" event handler, use .delegate() like this:

$('#parent').delegate('children', 'click', function() { /* do something */ });

This way you will be able to select new rows that were added.


Just to know, .live() is deprecated but it is used by some old plugins like datatables and others so I changed jQuery version to 1.7.2.

Also, I used fnAddData() instead of fnDraw() but this doesn't matter, it also caused the same issue you got and I found a "solution" according to that (that's why I assume that is "tested and working").


To be honest, I can't give you a detailed explanation about why this issue happens (It seems like a bug) but I got a possible "solution" and hope it helps you.

Please read the comments that are in code, check it (maybe this could give you another perspective for what you need to do) also check your browser console when needed.

like image 40
Oscar Jara Avatar answered Nov 15 '22 03:11

Oscar Jara