Row.add() fails after doing a DOM sort
Row.add() fails after doing a DOM sort
I am using DataTables 1.10.2. Both my row.add() and DOM sorting are working fine -- initially. Meaning on initial load table load, row.add() is working. But after I do a DOM sort on a column, suddenly row.add() is not functioning anymore.
The browser console shows that the error is occurring at line 213 of the jquery.dataTables.js ( (_pluck_order function):
out.push( a[ order[i] ][ prop ][ prop2 ] );
And the error is:
"Unable to get property '6' of undefined or null reference"
Any ideas?
My DataTable initialization:
$(document).ready(function() {
/*** START: DataTable functions for sorting on DOM table fields ***/
/* Create an array with the values of all the input boxes in a column */
$.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('input', td).val();
} );
}
/* Create an array with the values of all the input boxes in a column, parsed as numbers */
$.fn.dataTable.ext.order['dom-text-numeric'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('input', td).val() * 1;
} );
}
/* Create an array with the values of all the select options in a column */
$.fn.dataTable.ext.order['dom-select'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('select', td).val();
} );
}
/* Create an array with the values of all the checkboxes in a column */
$.fn.dataTable.ext.order['dom-checkbox'] = function ( settings, col )
{
return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
return $('input', td).prop('checked') ? '1' : '0';
} );
}
/*** END: DataTable functions for sorting on DOM table fields ***/
//Datatable transform
var t = $('#approveCrewDetTable').DataTable( {
"paging": false, //disable paging functionality since we want to use scrolling instead
"scrollY": "325px", //set vertical scroll area
"scrollCollapse": true,
"deferRender": true, //defers rendering for performance enhancement or so the API says
//"ordering": true,
//"info": true,
"columns": [
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": true, "orderable": true, "orderDataType": "dom-text", type: 'string' }, //In Time
{ "searchable": false, "orderable": false },
{ "searchable": true, "orderable": true, "orderDataType": "dom-text", type: 'string' }, //Out Time
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false },
{ "searchable": false, "orderable": false }
]
});
Add row code snippet:
var newRow = t.row.add( [
"<center> <input id='acCB" + counter + "' name='acCB" + counter + "' type='checkbox' onClick='javascript:toggleHighlightRow(this, " + counter + ");' /><input id='acEdited" + counter + "' name='acEdited" + counter + "' type='hidden' value='true'/></center>",
'',
"<center><select id='acOpDD" + counter + "' name='acOpDD" + counter + "' class='select' style='width:45px'></select></center>",
"<center><select id='acPosDD" + counter + "' name='acPosDD" + counter + "' class='select' style='width:35px'></select></center>",
"<center><select id='acShiftDD" + counter + "' name='acShiftDD" + counter + "' class='select' style='width:30px'><option value='1' >1</option><option value='2' >2</option><option value='3' >3</option></select></center>",
"<center><input type='text' size='9' id='acDetInDate" + counter + "' name='acDetInDate" + counter + "' onChange='checkDateTimeCollision();' /></center>",
"<center><input type='textbox' size='7' placeholder='hh:mm:ss' onblur='isValidTime(this);' /></center>",
"<center><input type='text' size='9' id='acDetOutDate" + counter + "' name='acDetOutDate" + counter + "' onChange='checkDateTimeCollision();' /></center>",
"<center><input type='textbox' size='7' placeholder='hh:mm:ss' onblur='isValidTime(this);' /></center>",
'<center>00:00</center>',
"<center><input type='button'/></center>",
"<center><input type='text' size='9' onblur='checkDateTimeCollision();'/></center>",
'<center></center>'
] ).draw().node();
This question has an accepted answers - jump to answer
Answers
Can you link to a test case showing the problem please, as per the forum rules?
Here is a test case based on my own example showing it working as expected: http://live.datatables.net/genezika/1/edit .
I would also suggest trying the latest version (the nightly) as the first port of call rather then continuing to use an old version.
Allan
Thanks for the reply Allan and I apologize for not being aware of the forum rules.
Here's my test case using all the latest versions (same as your original test case):
http://live.datatables.net/genezika/2/edit
And here are the steps to replicate:
And just some additional observations:
You can also add multiple rows successively and it is working fine. But the moment you sort "In Time" column, Add Row ceases to work.
The issue doesn't appear on regular (non DOM) sorting. In the updated test case below, I have enabled sorting on "Status" column which is just a regular string/text column. Add row still works after doing a sort on this column. Also interestingly enough, after doing the replication steps in my previous post, doing a sort on "Status" will make the new row that failed to show up initially, magically appear.
http://live.datatables.net/genezika/3/edit
Excellent - thanks for the test case.
I think I see the problem - you have
deferRender
enabled, but the sort function is usingcolumn().nodes()
. This is conflicting because the API method is trying to access the node before it exists (due todeferRender
).I don't think the API should be throwing quite that error, so I'll look into that, however, it is still an error state and to allow this to work (i.e. to be able to access the nodes) you need to remove the
deferRender
. Without that it appears to work as expected.Allan
That's it! You nailed it! Thank you very much and I appreciate the prompt response.