When I use server side processing in datatable the sorting works but the sort icon does not change and stays in same direction. Below is the code snippet of my datatable configuration.
$('#dtSearchResult').DataTable({
"filter": false,
"pagingType": "simple_numbers",
"orderClasses": false,
"order": [[0, "asc"]],
"info": true,
"scrollY": "450px",
"scrollCollapse": true,
"bLengthChange": false,
"searching": true,
"bStateSave": false,
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": VMCreateExtraction.AppSecurity.websiteNode() + "/api/Collection/SearchCustIndividual",
"fnServerData": function (sSource, aoData, fnCallback) {
aoData.push({ "name": "ccUid", "value": ccUid });
//Below i am getting the echo that i will be sending to Server side
var echo = null;
for (var i = 0; i < aoData.length; i++) {
switch (aoData[i].name) {
case 'sEcho':
echo = aoData[i].value;
break;
default:
break;
}
}
$.ajax({
"dataType": 'json',
"contentType": "application/json; charset=utf-8",
"type": "GET",
"url": sSource,
"data": aoData,
success: function (msg, a, b) {
$.unblockUI();
var mappedCusNames = $.map(msg.Table, function (Item) {
return new searchGridListObj(Item);
});
var data = {
"draw": echo,
"recordsTotal": msg.Table2[0].TOTAL_NUMBER_OF_RECORDS,
"recordsFiltered": msg.Table1[0].FILTERED_RECORDS,
"data": mappedCusNames
};
fnCallback(data);
$("#dtSearchResult").show();
ko.cleanNode($('#dtSearchResult')[0]);
ko.applyBindings(VMCreateExtraction, $('#dtSearchResult')[0]);
}
})
},
"aoColumns": [{
"mDataProp": "C_UID"
}, {
"mDataProp": "C_LAST_NAME"
}, {
"mDataProp": "C_FIRST_NAME"
}, {
"mDataProp": "C_USER_ID"
}, {
"mDataProp": "C_EMAIL"
}, {
"mDataProp": "C_COMPANY"
}],
"aoColumnDefs": [{ "defaultContent": "", "targets": "_all" },
//I create a link in 1 st column
]
});
There is some configuration that I am missing here. I read on datatable forums and the only issue highlighted by people was that draw should be same as what we send on server side.
For anyone looking for an answer to this. Sad but i had to write my own function as below:
function sortIconHandler(thArray, sortCol, sortDir) {
for (i = 0; i < thArray.length; i++) {
if (thArray[i].classList.contains('sorting_asc')) {
thArray[i].classList.remove('sorting_asc');
thArray[i].classList.add("sorting");
}
else if (thArray[i].classList.contains('sorting_desc')) {
thArray[i].classList.remove('sorting_desc');
thArray[i].classList.add("sorting");
}
if (i == sortCol) {
if (sortDir == 'asc') {
thArray[i].classList.remove('sorting');
thArray[i].classList.add("sorting_asc");
}
else {
thArray[i].classList.remove('sorting');
thArray[i].classList.add("sorting_desc");
}
}
}
}
tharrray-> The array of all row headers(You can just write a jquery selector for this).
sortCol->Column on which sort is clicked (Datatable param iSortCol_0)
sortDir -> Sorting direction (Datatable param sSortDir_0)
I know this is an old thread, but make sure you don't have an .off() somewhere associated with the tables capture group in jQuery. I had a click event that (for some reason) I attached an off function to.. Took me 3 days to find it.
Related
I'm trying to sum columns in a data table. But it is only suming the first page?
The two variables Requiredone and Bookedtwo only sum the values from the first page of the data, not the entire data set :s
var sTable = $('.datatable').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"bScrollCollapse": true,
"aaSorting": [[1, "desc"]],
"bServerSide": true,
"bProcessing": true,
"sAjaxSource": CycleTimeReport,
"aoColumns": [
{ "sName": "one", "sClass": "ellipsis" },
{ "sName": "two", "sClass": "ellipsis" }
],
"fnServerData": function (sSource, aoData, fnCallback) {
var data = new Object();
data.jsonAOData = JSON.stringify(aoData);
dataToSend = data;
$.ajax({
contentType: "application/json; charset=utf-8",
type: "POST",
url: sSource,
data: JSON.stringify(dataToSend),
success: function (msg) {
fnCallback(msg);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (document.Invoice.hostname == "localhost") {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.responseText);
}
}
});
},
"fnFooterCallback": function (nRow, aaData, iStart, iEnd, aiDisplay) {
var Requiredone = 0;
var Bookedtwo = 0;
for (var i = 0; i < aaData.length; i++) {
Requiredone+= aaData[i][2] * 1;
Bookedtwo += aaData[i][3] * 1;
}
},
"oLanguage": {
"sSearch": "_INPUT_"
},
"fnInitComplete": function (oSettings, json) {
},
"bSortCellsTop": true
});
You are using server-side processing of the data. So your datatable-object only has the data for the currently displayed page. You have to implement the sum on the server-side and add it to the JSON-response or do it in an extra ajax-request.
Another option would be to disable the server-side processing and pre-populate the table element or fill the aaData-property of the datatales-settings with a json object containing all data.
I have the following code where I want to use server side to lazy load my data. My goal is to display 10 records per page. The rest of the data should be loaded as and when the user clicks on a particular page.
What's happening now is that the datatable displays all the records at once. Can someone help me fix this issue?
var table = $("#members").DataTable({
"processing": true,
"serverSide": true,
paging: true,
"pagingType": "full_numbers",
"iDisplayLength": "10",
"length": "10",
ajax: {
url: "/api/members",
dataSrc: "",
},
columns: [
{
data: "cardNumber"
},
{
data: "registrationDate",
},
{
data: "fullName",
},
{
data: "address"
},
{
data: "phoneNumber"
},
{
data: "email"
}
]
});
Here's the API code:
// GET /api/members
public IEnumerable<MemberDto> GetMembers(string query = null)
{
var membersQuery = _context.Members.ToList();
if (!String.IsNullOrWhiteSpace(query))
membersQuery = membersQuery.Where(c => c.FullName.Contains(query.ToUpper())).ToList();
var memberDtos = membersQuery.ToList()
.Select(Mapper.Map<Member, MemberDto>);
return memberDtos;
}
I use jQuery DataTable :
$(document).ready(function() {
var table = $('#t_list').DataTable({
"language": {
"decimal": ",",
"thousands": " ",
"emptyTable": _getText("datatable.resultat.zero"),
"info": _getText("datatable.zone.statut.info"),
"infoEmpty": "",
"infoFiltered": _getText("datatable.zone.statut.filtre"),
"lengthMenu": _getText("datatable.zone.nb.affichage"),
"loadingRecords": _getText("datatable.resultat.chargement"),
"processing": _getText("datatable.resultat.processing"),
"search": _getText("datatable.zone.filtre"),
"zeroRecords": _getText("datatable.resultat.zero"),
"paginate": {
"first": _getText("datatable.btn.premier"),
"previous": _getText("datatable.btn.prcdt"),
"next": _getText("datatable.btn.svt"),
"last": _getText("datatable.btn.dern")
}
},
"pagingType": "full_numbers",
"serverSide": true,
"ajax": "<c:url value='/ajaxDataTableListUsers' />",
"columns": [{
"data": "username"
}, {
"data": "email"
}, {
"data": "salary"
}, {
"data": "id"
}],
"columnDefs": [{
"targets": 2,
"className": "alignDroite"
}, {
"targets": 3,
"render": function(data, type, row, meta) {
var client_noms = row.username; < c: url
var = "url_edit"
value = "/edit" / >
var url_edit = "${url_edit}?id=" + data;
return '<div style="text-align:center;"><img src="resources/images/edit.png" /> ' +
'<img src="resources/images/cross.png" /></div>';
}
}]
});
});
As you can see there is the thousands parameter in the language option. But at runtime the formatting is not applied :
So why is the formatting not applied ?
-- EDIT --
Source of the data is here :
#Override
#Transactional
public List<User> list(int start, int length, String search, int triIdx, String ordreTri) {
Criteria criteres = sessionFactory.getCurrentSession().createCriteria(User.class);
if (!search.equals("")) {
if (NumberUtils.isNumber(search))
criteres.add(Restrictions.like("salary", Double.parseDouble(search)));
else
criteres.add(Restrictions.like("username", search, MatchMode.ANYWHERE));
}
criteres.setFirstResult(start);
criteres.setMaxResults(length);
if (ordreTri.equals("asc")) {
switch (triIdx) {
case 0:
criteres.addOrder(Order.asc("username"));
break;
case 1:
criteres.addOrder(Order.asc("email"));
break;
case 2:
criteres.addOrder(Order.asc("salary"));
break;
default:
criteres.addOrder(Order.asc("username"));
break;
}
} else {
switch (triIdx) {
case 0:
criteres.addOrder(Order.desc("username"));
break;
case 1:
criteres.addOrder(Order.desc("email"));
break;
case 2:
criteres.addOrder(Order.desc("salary"));
break;
default:
criteres.addOrder(Order.desc("username"));
break;
}
}
criteres.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
#SuppressWarnings("unchecked")
List<User> listUser = (List<User>) criteres.list();
return listUser;
}
You don't show the source of your data.
The documenation of Datatables (https://datatables.net/manual/i18n) says that the thousands and decimal options are used when parsing your data, so that sorting can happen correctly. It doesn't look like Datatables is designed to format your data, just parse it. You should format your data as you wish it to be displayed.
I have a dataTables table at http://communitychessclub.com/test.php
My problem is I need to make an entire table row clickable to a link based on a game#. The table lists games and user should click on a row and the actual game loads.
I am unable to understand the previous solutions to this problem. Can somebody please explain this in simple terms?
I previously did this at http://communitychessclub.com/games.php (but that version is too verbose and does disk writes with php echo)
with
echo "<tr onclick=\"location.href='basic.php?game=$game'\" >";
<script>$(document).ready(function() {
$('#cccr').dataTable( {
"ajax": "cccr.json",
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
}
],
"columns": [
{ "data": "game" },
{ "data": "date" },
{ "data": "event" },
{ "data": "eco" },
{ "data": "white_rating" },
{ "data": "white" },
{ "data": "black_rating" },
{ "data": "black" }
]
} );
} );</script>
"cccr.json" looks like this and is fine:
{
"data": [
{
"game": "5086",
"date": "09/02/2013",
"event": "135th NYS Ch.",
"eco": "B08",
"white": "Jones, Robert",
"white_rating": "2393",
"black": "Spade, Sam",
"black_rating": "2268"
},
...
You can do it this way:
Use fnRowCallback to add a game-id data-attribute to your datatable rows
...
{ "data": "black" }
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
//var id = aData[0];
var id = aData.game;
$(nRow).attr("data-game-id", id);
return nRow;
}
This will give each row in your table a game id attribute e.g:
<tr class="odd" data-game-id="5086">
Then create a javascript listener for the click event and redirect to the game page passing the game id taken from the tr data-attribute:
$('#cccr tbody').on('click', 'tr', function () {
var id = $(this).data("game-id");
window.location = 'basic.php?game=' + id;
}
What I want is to get row data when users click on the table's tbody but I keep getting undefined for these datatables functions.
Data comes from a node-mysql module. And for testing purposes, after the table is initialized and data's propertly arrived I've set:
"fnDrawCallback" : function() {
console.log('this:' + this);
console.log('oTable.fnGetData():' + oTable.fnGetData());
console.log('JSON.stringify(oTable.fnGetData():' + JSON.stringify(oTable.fnGetData()));
console.log('JSON.stringify(oTable.fnGetData():' + JSON.stringify(oTable.fnGetData()[0]));
console.log('oTable.fnGetData()[0]:' + oTable.fnGetData()[0]);
},
The result is this:
this:[object Object] tables_offline.js:40
oTable.fnGetData():[object Object],[object Object],[object Object] tables_offline.js:41
JSON.stringify(oTable.fnGetData():[{"id":1,"age":"23","vol":26227,"tlg":4.93,"r":18.15},{"id":2,"age":"13","vol":6378,"tlg":3.97,"r":16.76},{"id":3,"age":"54","vol":131626,"tlg":6.49,"r":11.1}] tables_offline.js:42
JSON.stringify(oTable.fnGetData()[0]:{"id":1,"age":"23","vol":26227,"tlg":4.93,"r":18.15} tables_offline.js:43
oTable.fnGetData()[0]:[object Object]
It's not an array... Maybe this is the weird thing.
I've tried debugging with chrome, setting
$('#myTable').on('click', 'tr', function(){
var oTable = $('#myTable').DataTable();
debugger;
});
And here's a screenshot of what's coming from the variable oTable. I'm not sure but shouldn't I be able to see the functions right there? I can't query something like oTable.fnGetData() 'cause it's undefined.
Let me know if you need something else from my side in order for you to help me.
EDIT
What I want basicaly is to get row data when users click on the table's tbody. I can't get there since oTable = $('#myTable').DataTable(); oTable.fnGetData()' throws undefined.
I'll try to clarify a bit more.
tables_offline.js is the file that loads the datatable, there I define my oTable variable. While searching for help I came across this post (I'm using mData for the columns definition) and I'm not sure if this is the case but it may help.
I make use of fnDrawCallback just for testing oTable in the console, it's not part of the original code.
var oTable = $("#myTable").dataTable({
'fnServerParams': function (aoData) {
aoData.push({ "name": "startDate", "value": startDate });
aoData.push({ "name": "endDate", "value": endDate });
},
'sAjaxSource': '/url',
'sAjaxDataProp': '',
'bProcessing': true,
'sDom':'t',
"aoColumns": [
{ "bVisible": false, "mDataProp": "pcrc_id"},
{ "sWidth": "25%","sTitle": "age", "mDataProp": "pcrc"},
{ "sWidth": "25%","sTitle": "Vol", "mDataProp": "volumen"},
{ "sWidth": "25%","sTitle": "tlg", "mDataProp": "tlg"},
{ "sWidth": "25%","sTitle": "r", "mDataProp": "reitero",
"mRender": function ( data, type, full ) {
return data + '%';
}
}
],
"oLanguage": {
"sUrl": "/javascripts/i18n/dataTables.Spanish.json"
},
"aaSorting": [[ 0, "desc" ]],
"bSort": false,
"bInfo" : false,
"bPaginate": false,
"fnDrawCallback" : function() {
console.log('this:' + this);
console.log('oTable.fnGetData():' + oTable.fnGetData());
console.log('JSON.stringify(oTable.fnGetData():' + JSON.stringify(oTable.fnGetData()));
console.log('JSON.stringify(oTable.fnGetData()[0]:' + JSON.stringify(oTable.fnGetData()[0]));
console.log('oTable.fnGetData()[0]:' + oTable.fnGetData()[0]);
},
"bFilter": false
});
EDIT 2
New screenshot after accesing oTable when a row's clicked. If I dig deep into context I see the data but it's the full thing, not just the row clicked. I'd like to use a function to get clicked row data.
Remove the fnDrawCallback stuff, I think it's distracting you from the actual problem.
Try this:
var oTable = $("#myTable").dataTable({
'fnServerParams': function (aoData) {
aoData.push({ "name": "startDate", "value": startDate });
aoData.push({ "name": "endDate", "value": endDate });
},
'sAjaxSource': '/url',
'sAjaxDataProp': '',
'bProcessing': true,
'sDom':'t',
"aoColumns": [
{ "bVisible": false, "mDataProp": "pcrc_id"},
{ "sWidth": "25%","sTitle": "age", "mDataProp": "pcrc"},
{ "sWidth": "25%","sTitle": "Vol", "mDataProp": "volumen"},
{ "sWidth": "25%","sTitle": "tlg", "mDataProp": "tlg"},
{ "sWidth": "25%","sTitle": "r", "mDataProp": "reitero",
"mRender": function ( data, type, full ) {
return data + '%';
}
}
],
"oLanguage": {
"sUrl": "/javascripts/i18n/dataTables.Spanish.json"
},
"aaSorting": [[ 0, "desc" ]],
"bSort": false,
"bInfo" : false,
"bPaginate": false,
"bFilter": false
});
oTable.$('tr').click( function () {
var data = oTable.fnGetData( this );
console.log(data);
} );
Note that the oTable var is still in scope so you don't need to use var oTable = $('#myTable').DataTable().
This example is copied verbatim from the Datatables API documentation