Fixed rows sorting in datatables - javascript

I want to establish some fixed rows in head of the datatable.
This is my datatable settings:
var oTable = $('#transactions').dataTable( {
"aaSorting": [ [0,'desc'] ],
"bFilter": false,
"bSort": true,
"aaSorting": [[3,'desc']], // default search colums
// "aaSortingFixed": [[3,'desc']],
"bPaginate": true,
"bProcessing": true,
"sPaginationType": "full_numbers",
"asStripeClasses": [ 'monitoring-table-new' ],
"bAutoWidth": false,
"aoColumns": [
{ "sType": "custom",
"sClass": "td-date-size-cell",
"fnRender": function ( oObj, sVal ) {
return '<div class="monitoring-head-new leadencolor"><div class="form-border"><span class="date"><em>' + sVal + '</em></span></div></div>';
}
},
{ "sType": "custom",
"sClass": "td-transaction-size-cell",
"fnRender": function ( oObj, sVal ) {
return '<div class="monitoring-head-new leadencolor"><div class="form-border"><span class="transaction"><em>' + sVal + '</em></span></div></div>';
}
},
{ "sType": "custom",
"sClass": "td-client-size-cell",
"fnRender": function ( oObj, sVal ) {
return '<div class="monitoring-head-new leadencolor"><div class="form-border"><span class="client"><div>' + sVal + '</div></span></div></div>';
}
},
{ "sType": "custom",
"sClass": "td-value-size-cell",
"fnRender": function ( oObj, sVal ) {
return '<div class="monitoring-head-new leadencolor"><div class="form-border"><span class="value"><em>' + sVal + '</em></span></div></div>';
}
},
{ "sType": "custom",
"sClass": "td-status-size-cell",
"fnRender": function ( oObj, sVal ) {
return '<div class="monitoring-head-new leadencolor"><div class="form-border"><span class="status"><div>' + sVal + '</div></span></div></div>';
}
},
],
"sAjaxSource": '<?php echo url_for('#test?sf_format=json'); ?>',
} );
I have done in the following way:
jQuery.fn.dataTableExt.oSort['custom-asc'] = function(x,y) {
if (x.indexOf("MY VALUE") != -1) return -1; // keep this row at top
if (y.indexOf("MY VALUE") != -1) return 1; // keep this row at top
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
};
jQuery.fn.dataTableExt.oSort['custom-desc'] = function(x,y) {
if (x.indexOf("MY VALUE") != -1) return 1; // keep this row at top
if (y.indexOf("MY VALUE") != -1) return -1; // keep this row at top
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
};
This will keep in top position the rows which have "MY VALUE" in text. But the problem is that when I sort on other column, the "fixed" row is not remaining on top of the table.
Any solutions?

Just don't sort it. Use a tfoot like so -
<thead> ... </thead>
<tfoot style="display: table-row-group"> ... </tfoot>
<tbody> ... </tbody>

This is not easy, one thing you could do is mix your custom sorting with a custom datasource sorting tha customizes your datasource
// var oTable;
var onTopValues = new Array("Litige", "5410");
/* disable asc sorting for specific rows */
jQuery.fn.dataTableExt.oSort['custom-asc'] = function(x,y) {
if (isOnTop(x)) return -1; // keep this row at top
if (isOnTop(y)) return 1; // keep this row at top
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
};
jQuery.fn.dataTableExt.oSort['custom-desc'] = function(x,y) {
if (isOnTop(x)) return -1; // keep this row at top
if (isOnTop(y)) return 1; // keep this row at top
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
};
function isOnTop(s) {
// search for on top values
for (var i = 0; i < onTopValues.length; i++) {
if (s === onTopValues[i]) {
return true;
}
}
return false;
}
//custom datasource
$.fn.dataTableExt.afnSortData['custom-ontop'] = function ( oSettings, iColumn )
{
var aData = [];
//prepare the data
$('td:eq('+iColumn+')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function(){
//If the last column of this row should stay on top, return the value of the
//last row as datasource
if(isOnTop($(this).closest('tr').find('td:last').text())){
aData.push($(this).closest('tr').find('td:last').text());
}else{
//otherwise return this row as datasource
aData.push($(this).text());
}
});
return aData;
};
$(document).ready(function() {
/* Apply custom classes to table headers */
$.fn.dataTableExt.oStdClasses.sSortAsc = "custom_asc";
$.fn.dataTableExt.oStdClasses.sSortDesc = "custom_desc";
oTable = $('#transactions').dataTable({
"aoColumnDefs": [ { aTargets: [0,1,2,3], sType: "custom"}] ,
"aoColumns": [
{ "sSortDataType": "custom-ontop" },
{ "sSortDataType": "custom-ontop" },
{ "sSortDataType": "custom-ontop" },
{ "sSortDataType": "custom-ontop" },
{ "sSortDataType": "custom-ontop" }
],
"aaSorting": [],
"aaData": [
[ "2012-01-2", "2", "Local <br>0312313213", 20, "Litige" ],
[ "2012-03-22", "25", "Local <br>35313313213", 5540, "Valid" ],
[ "2012-01-2", "2", "Local <br>0312313213", 10, "Valid" ],
[ "2012-03-22", "25", "Local <br>35313313213", 5410, "Valid" ]
]
});
});
Basically you are still using your sorting function but you pass them a custom datasource that forces the values to stay on top. This assume that you are sorting on the last column, but you can add your logic to it.
http://jsbin.com/eroyac/4/edit#preview

This way i can lock the first row, and the sorting only affects the row after this one. Check this page for other options : http://datatables.net/reference/option/orderFixed
$('#budgytbl').dataTable({
"orderFixed": [ 0, 'asc' ]
})
<table id="budgytbl"...
<tbody>
<tr>
<td></td>
<td id="input-name"></td>
<td id="input-parent"></td>
</tr>
#foreach ($categories as $category)
<tr>
...
</tr>
#endforeach
...

I have a simplier solution.
I create the second tbody in my table and just move all rows I need to persist in that another tbody like so:
initComplete: function() {
var self = this;
var api = this.api();
api.rows().eq(0).each(function(index) {
var row = api.row(index);
if (row.data()...) { // condition here
var $row_to_persist = $(row.node());
var $clone = $row_to_persist .clone();
$(self).find('tbody:last').append($clone);
$total_row.remove();
row.remove();
api.draw();
}
});
}

Related

What is the best way to extract all rows from Datatables under a criteria in Javascript

I'm currently working on a condominum program. The goal of this issue is when one Apartment row is clicked on the Parent table all the months - related to that apartment - must be displayed on the Child table.
The click/select/deselect is working fine but I can not obtain all the twelfth months.
This is my actual tables layout (example 1):
And this is my actual tables layout (example 2):
My code to childTable is:
var childTable = $('#child').DataTable( {
"pageLength": 12,
ajax: {
url: "ajax/query_pagquotas.php", // This is the URL to the server script for the child data
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var rows = data.data[i];
if (rows.ID === ID) {
return [rows];
}
}
} else {
return [];
}
}
},
columns: [
{ "data": "ID" },
{ "data": "DATA" },
{ "data": "MES" },
{ "data": "VALOR" },
{ "data": "METODO" },
{ "data": "ESTADO" },
{ "data": "OBS" }
]
} );
Thanks for your help Masters
[edited]
Ups! If condition at the end does not make the 'deselect' work...
This is my full code at the moment:
$(document).ready(function() {
var parentTable = $('#parent').DataTable( {
ajax: "ajax/dbfraccoes.php",
"language": {
"sSearchPlaceholder": "Apto ou Proprietário...",
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Portuguese.json",
},
"processing": true,
"scrollY": "200px",
"scrollCollapse": true,
"paging": false,
pageLength: 5,
select: {
style: 'single'
},
columns: [
{ "data": "ID","searchable": false },
{ "data": "APTO" },
{ "data": "FRACCAO"},
{ "data": "PROPRIETARIO" },
{ "data": "VALOR_QUOTA","searchable": false, className: "cssValores"},
{ "data": "OBS" }
]
} );
// tabela Child ------------------------------------------
var childTable = $('#child').DataTable( {
columnDefs: [{
targets: 6,
render: function(data, type, row, meta){
if(type === 'display' && data === 'EMITIDO'){
data = '<td style="text-align:center"><button type="button" class="btn btn-info btn-sm cssButton center" title="Emitido Aviso de Recibo a pagamento">EMITIDO</button></td>'+
'<div class="links">' +
'Editar ' +
'</div>';
}else if (type === 'display' && data === 'AGUARDA'){
data = '<td style="text-align:center"><button type="button" class="btn btn-warning btn-sm cssButton center" title="Limite de pagamento ultrapassado. Em período de tolerância.">AGUARDA</button></td>'+
'<div class="links">' +
'<a href="<?php echo WEB_URL;?>credit_debit/gest_quotas.php?spid='+
row['pqid']+'#insert">Editar</a> ' +
'</div>';
}
return data;
}
}],
"paging": false,
"searching": false,
"language": {
"zeroRecords": "<center>Clique na tabela acima, na linha do apartamento que pretende. <br/>Os dados da fracção/apartamento selecionado acima serão reflectidos nesta tabela</center>",
},
ajax: {
url: "ajax/query_pagquotas.php",
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
var rows = []; // create an empty array
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var row = data.data[i];
if (row.ID === ID) {
rows.push(row);
}
}
}
return rows;
},
},
columns: [
{ "data": "pqid" },
{ "data": "ID"},
{ "data": "DATA" },
{ "data": "MES"},
{ "data": "VALOR", className: "cssValores"},
{ "data": "METODO" },
{ "data": "ESTADO" },
{ "data": "OBS" }
]
} );
// This will load the child table with the corresponding data
parentTable.on( 'select', function () {
childTable.ajax.reload();
} );
//clear the child table
parentTable.on( 'deselect', function () {
childTable.ajax.reload();
} );
} );
The simplest way to adjust your existing code, is to change the logic in your dataSrc: function (data) {...}.
At the moment, you are only creating an array of one item.
So, instead you can do this:
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
var rows = []; // create an empty array
if ( selected.any() ) {
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var row = data.data[i]; // change the variable name to "row"
if (row.ID === ID) {
rows.push(row); // add the new row to your array of rows
}
}
}
return rows; // return your array of rows
}
The most important line here is: rows.push(row); which is how JavaScript adds a new item to the end of an array.
So, now at the end of your dataSrc function you will either have an empty array [] if no rows were selected, or you will have an array of rows which match your ID.
That should solve your current problem.
The above approach should work - but it involves fetching every child row, every time - and then filtering out the ones you do not want to show.
You can probably improve on this by submitting the ID of the selected row as part of the child table's ajax URL. You can move the relevant code from its current location into your parentTable's on(select) function:
var selectedID = -1
parentTable.on( 'select', function () {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
selectedID = selected.data().ID;
}
childTable.ajax.reload();
} );
I do not know how you have implemented your ajax/query_pagquotas.php, so I am not sure of the best way to pass the selectedID parameter to it.
Normally I would append it as a query parameter in your ajax parameters:
data: 'id=' + selectedID
You may already know how to do this yourself.
Once you have passed the selectedID to your PHP, then you can use it to return only the records you want to display - and you can remove all of the existing dataSrc: function (data) {...} logic from your child table definition.

Filter Datatables after Ajax call

I'm working in CodeIgniter and i have a DataTable, i want to filter the data from the DT after the ajax has been called. I'm trying to do that by filtering the table, but it's not working.
Here's the JS Code.
$(function () {
var tableRep= $("#tblreport").dataTable({
responsive: true, filter:true, order: [[ 1, "desc" ]],
processing: true, serverSide: true,
ajax: { "url": baseurl+"reports/Report/dataTable", "type": "POST" },
columns:
[
{data:"idReport",},
{data:"date"},
{data:"customer"},
{data:"status",visible:false},
{data:null,searchable:false,orderable: false,width:"120px", render: function (row)
{ if (row.status == "wait") {return '<a class="glyphicon glyphicon-search" data-toggle="modal" data-target="#report">Asign</a>'; }
else if (row.status == "process") {return '<a data-toggle="modal" data-target="#report">Edit</a>';} else return '';} }
],
columnDefs:
[
{ responsivePriority: 1, targets: 1 },
{ responsivePriority: 2, targets: -1 },
{ responsivePriority: 3, targets: 2 }
], fnCreatedRow: function( nRow, aData, iDataIndex ) {
if ( aData["status"] == "ready" ) { $('td', nRow).css('background-color', '#BEF781'); }
else if ( aData["status"] == "wait" ) { $('td', nRow).css('background-color', '#F2F5A9'); }
else { $('td', nRow).css('background-color', '#FFFFFF'); }
}})
});
var filteredData = tableRep.column(4).data().filter( function ( value, index ) {return value!="cancel" ? true : false;} );
Did you try this option?
var tableRep= $("#tblreport").dataTable({
//your config
})
.on('draw.dt', function () {
//Add here yours filters
});

jQuery datatable - unexpected vertical scrollbar

I am trying display data in jQuery datatable but, I am seeing unexpected vertical scrollbar.
Fiddler: https://jsfiddle.net/8f63kmeo/15/
HTML:
<table id="CustomFilterOnTop" class="table table-bordered table-condensed" width="100%"></table>
JS
var Report4Component = (function () {
function Report4Component() {
//contorls
this.customFilterOnTopControl = "CustomFilterOnTop"; //table id
//data table object
this.customFilterOnTopGrid = null;
//variables
this.result = null;
}
Report4Component.prototype.ShowGrid = function () {
var instance = this;
//create the datatable object
instance.customFilterOnTopGrid = $('#' + instance.customFilterOnTopControl).DataTable({
columns: [
{ title: "<input name='SelectOrDeselect' value='1' id='ChkBoxSelectAllOrDeselect' type='checkbox'/>" },
{ data: "Description", title: "Desc" },
{ data: "Status", title: "Status" },
{ data: "Count", title: "Count" }
],
"paging": true,
scrollCollapse: true,
"scrollX": true,
scrollY: "50vh",
deferRender: true,
scroller: true,
dom: '<"top"Bf<"clear">>rt <"bottom"<"Notes">i<"clear">>',
buttons: [
{
text: 'Load All',
action: function (e, dt, node, config) {
instance.ShowData(10000);
}
}
],
columnDefs: [{
orderable: false,
className: 'select-checkbox text-center',
targets: 0,
render: function (data, type, row) {
return '';
}
}],
select: {
style: 'multi',
selector: 'td:first-child',
className: 'selected-row selected'
}
});
};
Report4Component.prototype.ShowData = function (limit) {
if (limit === void 0) { limit = 2; }
var instance = this;
instance.customFilterOnTopGrid.clear(); //latest api function
instance.result = instance.GetData(limit);
instance.customFilterOnTopGrid.rows.add(instance.result.RecordList);
instance.customFilterOnTopGrid.draw();
};
Report4Component.prototype.GetData = function (limit) {
//structure of the response from controller method
var resultObj = {};
resultObj.Total = 0;
resultObj.RecordList = [];
for (var i = 1; i <= limit; i++) {
resultObj.Total += i;
var record = {};
record.Description = "Some test data will be displayed here.This is a test description of record " + i;
record.Status = ["A", "B", "C", "D"][Math.floor(Math.random() * 4)] + 'name text ' + i;
record.Count = i;
resultObj.RecordList.push(record);
}
return resultObj;
};
return Report4Component;
}());
$(function () {
var report4Component = new Report4Component();
report4Component.ShowGrid();
report4Component.ShowData();
});
function StopPropagation(evt) {
if (evt.stopPropagation !== undefined) {
evt.stopPropagation();
}
else {
evt.cancelBubble = true;
}
}
ISSUE:
I am wondering why the vertical scrollbar is appearing and why I am seeing an incorrect count...? Is it because my datatable has rows with multiple lines? As I have already set the scrolly to 50vh, I am expecting all the rows to be displayed.
Note:
The table should support large data too. I have enabled scroller for that purpose as it is required as per the application design. To verify that click on "Load all" button.
Any suggestion / help will be greatly appreciated?
You just need to remove property " scroller: true" it will solve your problem.
For demo please check https://jsfiddle.net/dipakthoke07/8f63kmeo/20/

dataTable page length change issue

I am using dataTable 1.10. Everything works well but I got following situation. I think that dataTable not support this behaviour.
By default I set the page length be 10, then I click Next page, table display items from 11 to 20. NOW I change the page length to 25, table display item from 11 to 35. This is not the thing I suppose to have. Whenever I change the page length, I wish to display from 1st item.
Is it possible to handle the Page Length change event in dataTable and customize that function?
Thank for reading. Hope to receive help from you.
var tableHdr = '<table cellpadding="0" cellspacing="0" border="0" class="display" id="alertsList">'
+ '<thead><tr>'
+ '<th>Level</th><th>Monitor Name</th><th>Alert Message</th><th>Raised At</th><th>Action</th>'
+ '</tr></thead></table>';
$('#overview_content').html( tableHdr );
//global variable
oTable = $('#alertsList').dataTable( {
"pagingType": "full_numbers",
"bJQueryUI": true,
"aaData": alertsData,
"bAutoWidth": false,
"aaSorting" : [[3, "desc"]],
"aoColumns": [
{ "sTitle": "Level", "mData":"alert_level", "sWidth":"10%" },
{ "sTitle": "Monitor Name", "mData":"monitor_name", "sWidth":"20%" },
{ "sTitle": "Alert Message", "mData":"alert_message", "sWidth":"30%" },
{ "sTitle": "Raised At", "mData":"triggered_datetime", "sWidth":"20%"},
{ "sTitle": "Action", "mData":"id", "bSortable":false, "bSearchable":false, "sWidth":"20%"}
],
"columnDefs": [
{
"targets": 1,
"data":"monitor_name",
"render": function ( data, type, full, meta ) {
return escapeHTML(data);
}
},
{
"targets": 2,
"data":"alert_message",
"render": function ( data, type, full, meta ) {
if (data == null || typeof data == 'undefined')
{
return "";
}
var description = data.length > 30? data.substr(0,30) + '...': data;
return escapeHTML(description);
}
},
{
"targets": 4,
"render": function ( data, type, full, meta ) {
return ("<span style='cursor:pointer' id='dismiss_alert_" + full.id + "' class='dismiss'>Dismiss</span> | " +
"<span style='cursor:pointer' id='delete_alert_" + full.id + "' class='delete'>Delete</span> | " +
"<span style='cursor:pointer' id='details_alert_" + full.id + "' class='details'>Details</span>");
}
} ]
} );
Try this, I found it from datatable forum.
var t = $('#table-id').dataTable();
$('#length li').click(function () {
redrawWithNewCount(t, this.id);
});
function redrawWithNewCount(t, row_count) {
//Lifted more or less right out of the DataTables source
var oSettings = t.fnSettings();
oSettings._iDisplayLength = parseInt(row_count, 10);
t._fnCalculateEnd(oSettings);
/* If we have space to show extra rows (backing up from the end point - then do so */
if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()) {
oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
if (oSettings._iDisplayStart < 0) {
oSettings._iDisplayStart = 0;
}
}
if (oSettings._iDisplayLength == -1) {
oSettings._iDisplayStart = 0;
}
t.fnDraw(oSettings);
return t;
}

Javascript conditional formatting not recognized

I'm having a jQuery DataTable that is generated from a JSON file. All works fine, but as it comes to conditional formatting, I get stuck. The following script gives all cells in column 2 a 'positive' class (even negative integers). What's wrong with my if-statement?
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
if ( parseFloat(aData[1]) <= 0 ) {
jQuery('td:eq(1)', nRow).addClass('negative');
} else {
jQuery('td:eq(1)', nRow).addClass('positive');
}
return nRow;
}
thanks in advance!
edit: a part of the JSON file (the number I'm referring to is "punten":
[
{
"spel_id": "2012-09-24 15:43:56",
"locatie": "white room",
"speler": "Arne",
"punten": "17"
},
{
"spel_id": "2012-09-24 15:43:56",
"locatie": "white room",
"speler": "Bjorg",
"punten": "26"
}
]
and my js to generate the table (using DataTables):
$(document).ready( function() {
var oTable = $('#example').dataTable( {
"sAjaxSource": "json_gespeeldekaartings.php",
"aoColumns": [
{ "mData": "kaarting"},
{ "mData": "speler" },
{ "mData": "punten"}
],
"sAjaxDataProp": "",
"sPaginationType": "full_numbers",
"aaSorting": [],
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
if ( parseFloat(aData[1]) <= 0 ) {
jQuery('td:eq(1)', nRow).addClass('negative');
} else {
jQuery('td:eq(1)', nRow).addClass('positive');
}
return nRow;
}
} )
} );
inster of
if ( parseFloat(aData[1]) <= 0 ) {
use
if ( parseFloat(aData.punten <= 0 )
EDIT
try this :
remove fnRowCallback and use mRender for in this example :
...
"aoColumns": [
{ "mData": "kaarting"},
{ "mData": "speler" },
{ "mData": "punten",
"sType": "numeric",
"mRender": function ( data, type, full ) {
if(data > 0) return "<div class='positive'>" + data + "</div>"; // example
return "<div class='negative'>" + data + "</div>"; // example
}
}
],
...

Categories