Related
I am trying to load datatable from ajax response and then perform server-side processing. using this example
this is the response I am receiving from server :
{"msg":null,"code":null,"status":null,"result":[{"aNumber":"3224193861","bNumber":"3215910681","dateTime":"2017-06-05 09:44:22.0","duration":778,"imei":"47350901163665"},{"aNumber":"3224193861","bNumber":"3028540439","dateTime":"2017-04-26 18:53:23.0","duration":266,"imei":"31489802062929"}],"draw":1,"limit":1000,"recordsFiltered":13419,"recordsTotal":13419}
this my javascript code to handle ajax and datatable.
function showDataTable(anumber, startdate, enddate) {
var cdrReqParams = {};
cdrReqParams.draw = '1';
cdrReqParams.offset = 0;
cdrReqParams.newRequest = '1';
cdrReqParams.totalRecords = '1';
cdrReqParams.lookInCol = 'aNumber';
cdrReqParams.lookInVal = anumber;
cdrReqParams.fromDate = startdate;
cdrReqParams.toDate = enddate;
var jsonStr = JSON.stringify(cdrReqParams);
console.log(jsonStr);
API.call("http://localhost:8050/phpservice/json.php", 'POST', function(data) {
basicData = data.result;
console.log(basicData);
oTable = $("#table").dataTable({
bJQueryUI: true,
bPaginate: true,
sPaginationType: "full_numbers",
bFilter: false,
bInfo: false,
bProcessing: true,
bServerSide: true,
aaData: [basicData],
aoColumns: [{
"sTitle": "ANUMBER",
"mData": "aNumber"
}, {
"sTitle": "BNUMBER",
"mData": "bNumber"
}, {
"sTitle": "DATETIME",
"mData": "dateTime"
}, {
"sTitle": "DURATION",
"mData": "duration"
}, {
"sTitle": "IMEI",
"mData": "imei"
}]
});
}, function(error) {
console.log(error);
}, jsonStr);
}
By doing this, I am receiving 2 errors
DataTables warning: table id=table - Requested unknown parameter
'aNumber' for row 0, column 0. For more information about this error,
please see http://datatables.net/tn/4
and
Invalid JSON Response.
Is there any workaround for this type of problem, In which first, you will perform ajax call and from received data, you will populate datatable with server side processing ??
I hope someone will give me a hint at least.
With datatable 1.10,(i think you may be using an earlier version), you can populate and format the data in the cells, by using the columns.data property:
columns: [
{ data: "", defaultContent: " " },
{ data: null,
defaultContent: " ",
render: function (data, type, row, meta) {
return data.ID;
}
}
]
I have been trying to follow this approach of row grouping described in the following link. http://www.datatables.net/examples/advanced_init/row_grouping.html
However while implementing the drawCallback function I had to change the name to "fnDrawCallback" for my datatable to recognize this function and also declare var api as var api = this.oApi._fnGetTrNodes( settings ); instead of the way described in the example (var api = this.api();) as otherwise I was getting an error. However now I am still getting a similar error while defining the rest of function if I follow the syntax and keywords given in the example. That is ,
var rows = api.rows( {page:'current'} ).nodes();
var last=null;
api.column(2, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) {
$(rows).eq( i ).before(
'<tr class="group"><td colspan="5">'+group+'</td></tr>'
);
The error I get is "undefined is not a function " for the drawCallback function. I tried a lot trying to find a different way of writing the same function but I cannot understand why this doesn't work and why I had to change the api declaration too.
I am very new to this , so if someone could explain what the correct format would be to write this function without this error I would really appreciate it !
Please find my Jquery part listed below. Thanks in advance !!
$(document).ready(function(){
var oTable = $("#tableTenants").dataTable({
"bProcessing": true,
"sAjaxSource": "/api/alltenantstatistic.json?iDisplayStart=0&iDisplayLength=${totalCount}&sSortDir_0=asc",
"aoColumns": [
{ "mDataProp": "state","sClass": "student_rows" , "sWidth":"1%" },
{ "mDataProp": "name","sClass": "student_rows" , "sWidth":"20%"},
{ "mDataProp": "testAdmin","sClass": "student_rows" , "sWidth":"70%"},
{ "mDataProp": "totalStudentCount","sClass": "select_rows" , "sWidth":"2%", "bSortable": false },
{ "mDataProp": "totalPnPStudentCount","sClass": "select_rows" , "sWidth":"2%", "bSortable": false }
],
"aoColumnDefs": [
{ "fnRender": function(oObj) {
return '' + oObj.aData.state + '';
},
"bUseRendered": false,
"aTargets": [0]
},
{
"aTargets": [1],
"bVisible": false
},
],
"iDisplayLength": 10,
"order": [[ 1, 'asc' ]],
"fnDrawCallback": function ( settings ) {
console.log("hello");
var api = this.oApi._fnGetTrNodes( settings ); // Had to change this from this.api();
var rows = api.rows({page:'current'}).nodes(); // Giving an error
var last=null;
api.column(1, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) {
$(rows).eq( i ).before(
'<tr class="group"><td colspan="4">'+group+'</td></tr>'
);
last = group;
}
} );
},
"bLengthChange": true,
"bFilter": true,
"bAutoWidth": false,
//"bStateSave": true,
"sDom": "<'row-fluid'<'span5'l><'span7'f><'span2'>r>t<'row-fluid'<'span6'i><'span6'p>>",
"sPaginationType": "bootstrap",
"oLanguage": {
"sLengthMenu": "_MENU_",
"sEmptyTable": "No Organization Uploads available for this Tenant",
"sInfoEmpty": "",
"sProcessing": "Loading..."
}
});
Its due to jquery datatable version problem. use below libraries and code
<script src="//cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/plug-ins/725b2a2115b/integration/bootstrap/3/dataTables.bootstrap.js"></script>
<script src="//datatables.net/release-datatables/extensions/ColReorder/js/dataTables.colReorder.js"></script>
"drawCallback": function (settings) {
var api = this.api();
var rows = api.rows({ page: 'current' }).nodes();
var last = null;
api.column(1, { page: 'current' }).data().each(function (group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="group"><td colspan="3">' + group + '</td></tr>'
);
last = group;
}
});
},
I have a couple of drop downs that are populated from SharePoint using SPServices. This part works great. But then, I have a button that on click loads data from SharePoint and uses the dropdown texts as filter to fetch the data that will populate a table using the DataTables plugin. This part works only once; if I click the button again, nothing happens.
This is how I populate the dropdowns:
$(document).ready(function () {
var theYear; // Selected Year
var theRO; // Selected RO
//Fills the Dropdown lists (Year and RO)
$().SPServices({
operation: "GetListItems",
async: false,
listName: "{ListID}",
CAMLViewFields: "<ViewFields><FieldRef Name='Fiscal_x0020_Year' /><FieldRef Name='Regional_x0020_Office' /></ViewFields>",
completefunc: function (xData, Status) {
//Add Select Value option
$("#dropdown").prepend($('<option>', {
value: '',
text: 'Select Fiscal Year'
}));
$("#dropdownRO").prepend($('<option>', {
value: '',
text: 'Select Regional Office'
}));
//Fetching Data from SharePoint
$(xData.responseXML).SPFilterNode("z:row").each(function () {
var dropDown = "<option value='" + $(this).attr("ows_Fiscal_x0020_Year") + "'>" + $(this).attr("ows_Fiscal_x0020_Year") + "</option>";
var dropDownRO = "<option value='" + $(this).attr("ows_Regional_x0020_Office") + "'>" + $(this).attr("ows_Regional_x0020_Office") + "</option>";
$("#dropdown").append(dropDown);
$("#dropdownRO").append(dropDownRO);
/////////////Deletes duplicates from dropdown list////////////////
var usedNames = {};
$("#dropdown > option, #dropdownRO > option").each(function () {
if (usedNames[this.text]) {
$(this).remove();
} else {
usedNames[this.text] = this.value;
}
});
////Deletes repeated rows from table
var seen = {};
$('#myTable tr, #tasksUL li, .dropdown-menu li').each(function () {
var txt = $(this).text();
if (seen[txt]) $(this).remove();
else seen[txt] = true;
});
});
} //end of completeFunc
}); //end of SPServices
$('.myButton').on('click', function () {
run()
});
}); //End jQuery Function
This is the function I need to run every time I click on "myButton" after changing my selection in the dropdowns:
function run() {
theYear = $('#dropdown option:selected').text(); // Selected Year
theRO = $('#dropdownRO option:selected').text(); // Selected RO
var call = $.ajax({
url: "https://blah-blah-blah/_api/web/lists/getByTitle('Consolidated%20LC%20Report')/items()?$filter=Fiscal_x0020_Year%20eq%20'" + theYear + "' and Regional_x0020_Office eq '" + theRO + "'&$orderby=Id&$select=Id,Title,Fiscal_x0020_Year,Notices_x0020_Received,Declined_x0020_Participation,Selected_x0020_Field_x0020_Revie,Selected_x0020_File_x0020_Review,Pending,Pending_x0020_Previous_x0020_Yea,Controversial,GFP_x0020_Reviews,NAD_x0020_Appeals,Mediation_x0020_Cases,Monthly_x0020_Cost_x0020_Savings,Monthly_x0020_Expenditure,Regional_x0020_Office,Month_Number", //Works, filters added
type: "GET",
cache: false,
dataType: "json",
headers: {
Accept: "application/json;odata=verbose",
}
}); //End of ajax function///
call.done(function (data, textStatus, jqXHR) {
var oTable = $('#example').dataTable({
"aLengthMenu": [
[25, 50, 100, 200, -1],
[25, 50, 100, 200, "All"]
],
"iDisplayLength": -1, //Number of rows by default. -1 means All Records
"sPaginationType": "full_numbers",
"aaData": data.d.results,
"bJQueryUI": false,
"bProcessing": true,
"aoColumns": [{
"mData": "Id",
"bVisible": false
}, //Invisible column
{
"mData": "Title"
}, {
"mData": "Notices_x0020_Received"
}, {
"mData": "Declined_x0020_Participation"
}, {
"mData": "Selected_x0020_Field_x0020_Revie"
}, {
"mData": "Selected_x0020_File_x0020_Review"
}, {
"mData": "Pending"
}, {
"mData": "Pending_x0020_Previous_x0020_Yea"
}, {
"mData": "Controversial"
}, {
"mData": "GFP_x0020_Reviews"
}, {
"mData": "NAD_x0020_Appeals"
}, {
"mData": "Mediation_x0020_Cases"
}, {
"mData": "Monthly_x0020_Cost_x0020_Savings",
"fnRender": function (obj, val) {
return accounting.formatMoney(val);
}
}, {
"mData": "Monthly_x0020_Expenditure",
"fnRender": function (obj, val) {
return accounting.formatMoney(val);
}
}],
"bDeferRender": true,
"bRetrieve": true,
"bInfo": true,
"bAutoWidth": true,
"bDestroy": true,
"sDom": 'T&;"clear"&;frtip',
"oTableTools": {
"aButtons": ["xls"],
"sSwfPath": "../../Style Library/js/datatables/TableTools/media/swf/copy_csv_xls_pdf.swf",
},
"sSearch": "Filter",
"fnDrawCallback": function () {
//Add totals row
var Columns = $("#example > tbody").find("> tr:first > td").length;
$('#example tr:last').after('<tr><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td><td class="total"></td></tr>');
//Formating the Total row number to no decimals
$("#example tr:last td:not(:first,:last)").text(function (i) {
var t = 0;
$(this).parent().prevAll().find("td:nth-child(" + (i + 2) + ")").each(function () {
t += parseFloat($(this).text().replace(/[\$,]/g, '') * 1);
});
return parseInt(t * 100, 10) / 100;
});
//Format the monthly expenditure and savings to currency formatFormating the currency
var cell = new Array();
cell[0] = $('#example tr:last td:nth-child(12)').text();
cell[1] = $('#example tr:last td:nth-child(13)').text();
$('#example tr:last').find('td:nth-child(12)').html(accounting.formatMoney(cell[0]));
$('#example tr:last').find('td:nth-child(13)').html(accounting.formatMoney(cell[1]));
$('#example tr:last').find('td:last').hide();
} //hides extra td that was showing
}); //End of Datatable()
}); //End of call.done function
$('#theTableDiv').slideDown();
} //end of run() function
I'm not a programmer, I'm just trying to learn. I would appreciate any help. Thanks in advance
I would guess that you are replacing the part of the page where the button lives. (you really need to format your code more neatly for SO... use JSFiddle.net and their TidyUp button).
If that is the case you need to use a delegated event handler:
$(document).on('click', '.myButton', function () {
run()
});
This listens at a static ancestor of the desired node, then runs the selector when the event occurs, then it applies the function to any matching elements that caused the event.
document is the fallback parent if you don't have a convenient ancestor. Do not use 'body' for delegated events as it has odd behaviour.
I am using DataTable Jquery for bind list of records. I face below issue.
I am using jquery model popup for addnew and update record in MVC 4.0 Razor with no submit button only using ajax function. When I am click on "save" button and I want to update list with latest changes, but it can not. My code as below.
For Index page for list bind.
<script type="text/javascript">
$(document).ready(function () {
if (fnServerObjectToArray) {
var oTable = $('.datatable').dataTable({
"bJQueryUI": true,
"sScrollX": "",
"bSortClasses": false,
"aaSorting": [[0, 'asc']],
"bAutoWidth": true,
"bInfo": true,
"sScrollY": "100%",
"sScrollX": "100%",
"bScrollCollapse": true,
"sPaginationType": "full_numbers",
"bRetrieve": true,
"bProcessing": true,
"sAjaxSource": $('.datatable').attr('data'),
"aoColumns": [
{ sType: 'string' },
{ sType: 'string' },
{ sType: 'string' },
{ sType: 'string' },
{ bSortable: false }
],
"fnServerData": fnServerObjectToArray()
});
}
});
fnServerObjectToArray = function () {
return function (sSource, aoData, fnCallback) {
$.ajax({
"dataType": 'json',
"type": "GET",
"url": sSource,
"data": aoData,
"success": function (json) {
var a = [];
for (var i = 0, iLen = json.aaData.length; i < iLen; i++) {
var inner = [];
inner.push(json.aaData[i].Name);
inner.push(json.aaData[i].Price);
inner.push(json.aaData[i].Phone);
inner.push(json.aaData[i].Email);
inner.push("<a title='Edit Place' class='EditDialogPlacesToStay' href='/placetostay/" + json.aaData[i].Id + "/edit'><img src='/Content/images/icons/small/grey/pencil.png' title='Edit' /></a> <a class='DeleteConfirm' href='/placetostay/" + json.aaData[i].ID + "/delete'><img src='/Content/images/icons/small/grey/trashcan.png' title='Delete' /></a>");
a.push(inner);
}
json.aaData = a;
fnCallback(json);
},
"error": function (error) {
}
});
}
}
</script>
On save button in success function I call the location.reload().
But I could not bind the latest changes of records means List is not refreshed.
Please help me for same.
Wrap the datatable initialization into a function, like initDataTable(), and add the option bDestroy to the settings :
function initDataTable() {
if (fnServerObjectToArray) {
var oTable = $('.datatable').dataTable({
"bDestroy" : true, //<-- add this option
"bJQueryUI" : true,
...
//anything as above
});
}
}
$(document).ready(function () {
initDataTable();
});
when you want to refresh / reload, like by a click on a button :
<button id="refresh">Refresh</button>
$("#refresh").click(function() {
initDataTable();
});
here is a demo -> http://jsfiddle.net/cxe5L/
To avoid the cache-issue
jQuery dataTables has hardcoded cache : true into its AJAX-calls. You have "sAjaxSource": $('.datatable').attr('data'). I assume data holds the path to an external resource, like /data/getdata.asp or similar? Add a timestamp as param to that resource, like
sAjaxSource : $('.datatable').attr('data')+'?param='+new Date().getTime()
so the sAjaxSource becomes on the form
/data/getdata.asp?param=1401278688565
This is basically the same thing jQuery is doing, when cache : false is set on a AJAX-request.
location.reload() will refresh the page content and your
$(document).ready(function () {}
is executing again instead of getting the latest changes. Check weather your database has new records or not.
I use JQuery DataTable to bind and show my data. However, I can't add row number to generated grid from client side. Here my code:
HTML
<table id="applications_list" class="table table-bordered datagrid">
<thead>
<tr>
<th><?php echo __('No.'); ?></th>
<th><?php echo __('Application Code'); ?></th>
<th><?php echo __('Application Name'); ?></th>
<th><?php echo __('Created By'); ?></th>
<th><?php echo __('Created Date'); ?></th>
<th><?php echo __('Action'); ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Javascript
$('#applications_list').dataTable({
"bLengthChange": false,
"bFilter": true,
"bFilter": false,
"bProcessing": true,
"bServerSide": true,
"sPaginationType": "full_numbers",
"sAjaxSource": config.siteURL + "/applications/ajax_index",
"sServerMethod": "POST",
"aoColumns": [
{ "mData": null, "bSortable": false },
{ "mData": "app_applicationcode", "sName": "app_applicationcode" },
{ "mData": "app_applicationname", "sName": "app_applicationname" },
{ "mData": "app_createdby", "sName": "app_createdby" },
{ "mData": "app_createddate", "sName": "app_createddate" },
{ "mData": "app_applicationcode", "bSortable": false, "mRender": function(data) {
return '<i class="">x</i>'
}},
],
"aaSorting": [[ 0, 'asc' ]],
});
I read documentation here, but it won't work. Can anyone help me to solve this problem?
Best solution:
"columns": [
{ "data": null,"sortable": false,
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
},
......
]
For DataTables 1.10.4,
"fnCreatedRow": function (row, data, index) {
$('td', row).eq(0).html(index + 1);
}
Add following code in "fnRowCallback":
For Datatables 1.10
"fnRowCallback": function (nRow, aData, iDisplayIndex) {
var info = $(this).DataTable().page.info();
$("td:nth-child(1)", nRow).html(info.start + iDisplayIndex + 1);
return nRow;
}
The guide from official documentation didn't work on server side tables. The best answer I can get is from this answer (from another question), just to write a render function:
{
"data": "id",
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
}
Go upvote that answer.
Since none of the solutions here worked for me, here is my solution for a server-side.
add the extra <th></th> in your table, this is to mark where the number is to be inserted.
add the following right after initiating the table, the same way you would add "ajax": {"url":"somepage"},
"fnCreatedRow": function (row, data, index) {
var info = table.page.info();
var value = index+1+info.start;
$('td', row).eq(0).html(value);
},
3.At the location where the variables are defined for the table columns, add this column { "data": null,"sortable": false },
so it looks like this:
"columns": [
{ "data": null,"sortable": false },
......]
4. To get rid of the sorting icon (up-down arrow), select the second column by adding , "order": [[ 1, 'asc' ]], the same way you would add "ajax"....
This is possible by make use of fnPagingInfo api in the rowCallback to get the page and the display length and use it to calculate the row number like this:
For DataTables < 1.10
$('#example').dataTable({
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var page = this.fnPagingInfo().iPage;
var length = this.fnPagingInfo().iLength;
var index = = (page * length + (iDisplayIndex +1));
$('td:eq(0)', nRow).html(index);
}
});
For DataTables == 1.10
$('#example').dataTable({
"rowCallback": function( row, data, iDisplayIndex ) {
var info = this.api.page.info();
var page = info.page;
var length = info.length;
var index = = (page * length + (iDisplayIndex +1));
$('td:eq(0)', row).html(index);
}
});
NOTE: for DataTables < 1.10, you have to add the fnPageInfo.js script to your page
Official solution from DataTable:
table.on( 'order.dt search.dt', function () {
table.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
cell.innerHTML = i+1;
} );
} ).draw();
when we use Server Side Rendering, One of the Easy & Best Way for Display Auto Increment Sr No. instead of table row id... I used "Laravel Yajra DataTable"
simply use return meta.row + 1; .
see Below Example Code
columns: [
{data: 'SrNo',
render: function (data, type, row, meta) {
return meta.row + 1;
}
},
.... //your Code(Other Columns)
]
Or You can also Use like this
columns: [
{data: 'SrNo',
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
},
.... //your Code(Other Columns)
]
Assuming the <?php echo __('No.'); ?> is the primary key from database you can use columnDefs to add the key as row number to each cell of a row like this
"columnDefs": [{
"targets": '_all',
"createdCell": function(cell, cellData, rowData, rowIndex, colIndex) {
$(cell).attr({'data-pk': rowData[0]});
}
}]
Where rowData[0] will be the primary key value.
Just add return meta.row + 1 this inside render function. For Example.
{
data: "",
render: function(rec, type, row, meta) {
return meta.row + 1;
}
}