Call fnRowCallback on table redraw in datatable - javascript

I am doing some post processing in datatable in fnRowCallback. But they are not being called when the table is redrawn. (i.e, when some event like changing the number of displayed rows are called from UI, the table is redrawn)
$(document).ready(function () {
var oTable = $('#data').dataTable({
"bJQueryUI": true,
"bProcessing": true,
"bServerSide": true,
"bSort": false,
"sAjaxSource": "query.php",
"sPaginationType": "full_numbers",
"aoColumns": [
null,
null,
null,
],
"fnRowCallback": function (nRow, aData, iDisplayIndex) {
$(nRow).attr("id", aData[4]);
return nRow;
},
"fnDrawCallback": function( oSettings ) {
// How do I call fnRowCallback here?
// losing post processing because it is not being called after a redraw
}
});

I think your attempt to look up the actual row via jquery in $(nRow) does not work. nRow contains the whole row. You should just is as namespace for the jquery selector (second parameter) to restrict it to this particular row.
Like so:
$("selector",nRow).jqueryaction()
This works for me:
Html:
<tr>
<td>a</td>
<td class="boldmetight">b</td>
</tr>
<tr>
<td class="boldmetight">c</td>
<td>d</td>
</tr>.. etc
And the table definition with a rowcallback that bolds every cell with a specific class (just for example):
var otable = $("#datatable").dataTable({
"fnRowCallback": function(nRow, aData, iDisplayIndex) {
$('.boldmetight', nRow).html('<b>' + $('.boldmetight', nRow).text() + '</b>');
}
});
Look at this working Plunker

Related

Jquery DataTable unable to add rows using table.rows.add method

For some very funny reason, I am unable to add multiple rows to a simple table using dataTables. Here is the thing,
I am adding 4 rows to an html table using datatable, specifically using the table.rows.add method (link).
Below is the simple html code for it with a sample row already present in it.
<table id="items-table" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>ID</th>
<th>Item Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>Sample Object</td>
</tr>
</tbody>
</table>
And here is the javascript code for it.
// create a dataTable
var itemsTable = $("#items-table").DataTable({
paging: false,
searching: false
});
// add data as rows. Make sure to call the ```.draw``` method.
itemsTable.rows.add([{
"id": "1",
"item": "Aardvark"
}, {
"id": "2",
"item": "Red Bull"
}, {
"id": "3",
"item": "Jack in the Box"
}, {
"id": "4",
"item": "Chair"
}]).draw();
Error says:
DataTable warning: table id=items-table -Requested unknown parameter
'0' for row 1, column 0. For more information see this error.
Using
DataTables 1.10.12
jQuery v3.1.1
What is going wrong here?
You need to specify the columns.
// create a dataTable
var itemsTable = $("#items-table").DataTable({
paging: false,
searching: false,
columns: [{data: 'id'}, {data: 'item'}]
});
One workaround is to put all the data in a regular table and then initialize it as a dataTable, instead of adding individual rows.
You may want to add "fnDrawCallback": function in your Datatable initialization if you are using underscore.js templates or similar, and use function to bind events to rows after the table is redrawn. Another possible way to do this would be to use, order.dt or search.dt or page.dt events provided by Datatables to do this. Possibly like:
function bind_feedback_behavior(){
$('table.program-status')
.on( 'order.dt', function () { enable_feedback_behavior(); } )
.on( 'search.dt', function () { enable_feedback_behavior(); } )
.on( 'page.dt', function () { enable_feedback_behavior(); } );
}

Call fnServerData in DataTables 1.10

So I'm looking at this example and am trying to make it work for me.
I want to add the select options to my table when I use server side processing. Since I have only used version 1.10 I always get confused when I see this old API.
I don't understand how I can use this function in 1.10:
"sAjaxSource": "../examples_support/server_processing.php",
"fnServerData": function ( sSource, aoData, fnCallback ) {
/* ... additional variables ... */
$.getJSON( sSource, aoData, function (json) {
/* Create the select elements on the first run */
if ( json.sEcho == 1 )
{
$("tfoot th").each( function (i) {
/* Insert the select menu */
this.innerHTML = fnCreateSelect(json.select[i]);
/* Add the event listener for the newly created element */
$('select', this).change( function () {
oTable.fnFilter( $(this).val(), i );
} );
} );
}
/* DataTables callback */
fnCallback(json)
} );
}
The converting guide just lists fnServerData as ajax.
This is my initialization code:
$('#dataTables-outputTest').DataTable({
"processing": true,
"serverSide": true,
"ajax": "/TestData/data-source",
"columns": [
{ "data": "thing1",
"searchable": true},
{ "data": "thing2",
"searchable": true},
...
{ "data": "link",
"searchable": false,
"orderable": false},
],
"initComplete": function () {
this.api().columns().every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
}
});
How do I use that function and how do I have to rewrite it to work for me?
It seems I didn't understand what fnServerData did. It can be used to send additional data to the server from the client. So it's the oposite of what I'm trying to do.
I managed to do this by using this code:
"processing": true,
"serverSide": true,
ajax: {
url: '/MyApp/data-source',
data: function ( data ) {
data.someKey = "someValue";
},
},
Then when I print my request on the server I find a new object in the dictionary:
'someKey': ['someValue']

Cannot reinitialise DataTable

I'm following this link to implement server side pagination in jquery datatable.
I have index view which load partial view with jquery data table. This partial view calls asp.net-mvc controller and return json data which should be injected into jquery datatable. But on initial render of my index view I'm getting following error
DataTables warning: table id=dataTables-table - Cannot reinitialise DataTable
so I tried to add into partial view where jquery datatable is initialized
"bRetrieve": true,
but that not helped.
partial view jq. data table initialization looks like this
<script type="text/javascript">
$(document).ready(function () {
$('#dataTables-table').dataTable({
"bRetrieve": true,
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/MyController/MyAction",
"sServerMethod": "POST",
"aoColumns": [
{ "mDataProp": "String A" },
{ "mDataProp": "String B" },
{ "mDataProp": "String C" }],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
var birthday = new Date(parseInt(aData.Birthday.replace("/Date(", "").replace(")/", ""), 10));
$('td:eq(3)', nRow).html(birthday.getMonth() + 1 + "/" + birthday.getDate() + "/" + birthday.getFullYear());
}
});
});
</script>
What I'm missing here?
Update:
[HttpPost]
public JsonResult MyAction(JQueryDataTablesModel model)
{
int totalRecordCount;
int searchRecordCount;
var data = GetMyData(model.iDisplayStart, model.iDisplayLength, model.GetSortedColumns(),
out totalRecordCount, out searchRecordCount, model.sSearch);
return Json(new JQueryDataTablesResponse<MyObject>(data, totalRecordCount, searchRecordCount, model.sEcho));
}
Try adding option:
"destroy": true.

ng-click not working AngularJS and dataTables

I wrote a dataTables directive for AngularJS. Its working fine except that i trying to add an button to the row that removes an row with an ng-click.
In my opinion is that the problem occurs because the table row doesn't now the scope.
Can somebody help me out solving this problem.
jsFiddle Example: http://jsfiddle.net/A5Zvh/7/
My directive looks like this.
angular.module('DataTables', [])
.directive('datatable', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
require: 'ngModel',
template: '<table></table>',
link: function(scope, element, attrs, model) {
var dataTable = null,
options;
var buttons = jQuery.parseJSON(attrs['buttons']) || null;
options = {
"bJQueryUI": false,
"sDom": "<'row-fluid'<'span4'l><'span8 filter' <'pull-right'T> <'pull-right'f>>r>t<'row-fluid'<'span6'i><'span6'p>>",
"sPaginationType": "bootstrap",
"oTableTools": {
}
};
if(_.has(attrs, 'datatableOptions')) {
jQuery.extend(true, options, scope.$eval(attrs['datatableOptions']));
}
scope.$watch(attrs.ngModel, function(data) {
if(data && _.size(data.aaData) > 0 && _.size(data.aoColumns) > 0) {
_.extend(options, scope.$eval(attrs.ngModel))
dataTable = $(element).dataTable(options);
dataTable.fnClearTable();
dataTable.fnAddData(data.aaData);
}
});
}
}
})
I'm using Angular-datatbles, and I was trying to dynamically add, Edit & Remove links to the datatble rows and display modal on ng-click;
This was the solution for my case;
$scope.dtOptions.withOption('fnRowCallback',
function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$compile(nRow)($scope);
});
All the datatable binding code;
$scope.reloadData = function () {
$scope.dtOptions.reloadData();
};
$scope.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(2).renderWith(function (data, type, row) {
var html = '<i class="fa fa-pencil hidden-xs"></i> Edit' +
'<i class="fa fa-times hidden-xs"></i> Remove';
return html;
})
];
$scope.dtColumns = [
DTColumnBuilder.newColumn('name').withTitle('Name'),
DTColumnBuilder.newColumn('type').withTitle('Type'),
DTColumnBuilder.newColumn('id').withTitle(''),
];
$scope.dtOptions.withOption('fnRowCallback',
function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$compile(nRow)($scope);
});
I solved this by going through each td and calling $compile. Using the datatable row callback function. Hope this helps.
options.fnCreatedCell = function (nTd, sData, oData, iRow, iCol) {
$compile(nTd)($scope);
}
//or row
options.fnCreatedRow = function( nRow, aData, iDataIndex ) {
$compile(nRow)($scope);
}
The delete function in your controller isn't called because AngularJS doesn't know anything about DataTables's insertion of those elements to the DOM, thus ngClick directive within those elements isn't compiled and linked. So change:
dataTable.fnAddData(data.aaData);
To
dataTable.fnAddData(data.aaData);
$compile(element)(scope);
And to inject $compile service:
.directive('datatable', function () {
To
.directive('datatable', function ($compile) {
And your delete function is broken in the jsFiddle, hope that's not the case in your actual project!
You might want to give a look at the first couple of Zdam's post on this Google Groups thread, especially to his/her two linked jsFiddles. I basically copied them and they work at a basic level. I have not tried yet to get some action starting from a click on a row.
I see that you implemented a slightly different approach, recreating the <table> HTML node altogether. Not sure if this is causing issues.
By the way, on the scope.$watch call I had to make sure there was a third parameter set to true, in order to make value comparison (instead of reference comparison) on the returned resource$ object. Not sure why you don't need that.
fnCreatedCell be supplied in aoColumns or fnCreatedRow supplied to mRender
1 )fnCreatedCell is column based
ex :
tableElement.dataTable({
"bDestroy": true,
oLanguage : {
sLengthMenu : '_MENU_ records per page'
},
aoColumnDefs: [
{
bSortable: false,
aTargets: [ -1,-2,-3 ],
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$compile(nTd)($scope)
}
}
],
2 ) fnCreatedRow is a 'top level' callback
tableElement.dataTable({
"bDestroy": true,
oLanguage : {
sLengthMenu : '_MENU_ records per page'
},
aoColumnDefs: [
{
bSortable: false,
aTargets: [ -1,-2,-3 ]
}
],
"fnCreatedRow": function( nRow, aData, iDataIndex ){
compile(nRow)(scope);
},

jQuery Datatables fnRender row change

I want to add some class to row when I render a table, sample code:
$("#id").dataTable({
bProcessing: true,
sAjaxSource: com.mycompany.path.api.message[component],
aoColumns: [
{}, {},
{
sWidth: "37px",
fnRender: function(obj) {
return "<span>" + myData + "</span>";
}
}
]
});
In this example I could only control "td" tags, but I want to add some class for "tr" tag based on data that I get in fnRender() in cycle.
How I can do it with datatables?
Thanks,
Looks like in 1.7.3 available new functionality:
http://www.datatables.net/examples/advanced_init/row_callback.html

Categories