datatables print customize cell color - datatables

I'm tying to change the table cell color when printing a table.. The print cusomize fucntion is called and working correctly but the color doesn't change..
When I render the initial table I call rollCallback to set the cell color
rowCallback: function(row, data, index){
if(data.scores <= 1){
$(row).find('td:eq(2)').css('background-color', 'red');
}
if(data.scores > 1 && data.scores <=2 ){
$(row).find('td:eq(2)').css('background-color', 'yellow');
}
if(data.scores > 2){
$(row).find('td:eq(2)').css('background-color', 'green');
}
}
The in the print buttom. I use the same code to render the background color again
{
extend : 'print',
text : '<i class="fa fa-print fa-lg"></i>',
titleAttr : 'Print',
exportOptions : {
columns : [0,1,2,4]
},
customize: function(win,conf,table) {
table.rows().every(function(index,element) {
if(this.data().scores <= 1)
{
$(this).find('td:eq(2)').css('background-color', 'red');
}
if(this.data().scores > 1 && this.data().scores <=2 )
{
$(this).find('td:eq(2)').css('background-color', 'yellow');
}
if(this.data().scores > 2)
{
$(this).find('td:eq(2)').css('background-color', 'green');
}
});
}
}
The color does not change..
Im using
jquery-3.5.1
Datatables-1.10.21
buttons-1.6.3
Using #andrewjames answer I get a little better result.. The preview now has color.. but when ctrl-print is used from the browser I loose the style again.

Here is the approach mentioned in my other answer, but adapted for your specific circumstances.
In my test data I only have 3 columns, so I made one small change from your code - I changed this columns : [0,1,2,4] to this columns : [ 0, 1, 2 ].
Here is my starting table:
Here are some extra styles I added:
<style>
td.bg_red {
background-color: red;
}
td.bg_yellow {
background-color: yellow;
}
td.bg_green {
background-color: green;
}
</style>
I used the following embedded test data (instead of an ajax data source):
var dataSet = [
{ "name" : "Tiger Nixon",
"office": "London",
"scores" : 1 },
{ "name" : "Donna Snider",
"office": "New York",
"scores" : 2 },
{ "name" : "Airi Satou",
"office": "Tokyo",
"scores" : 3 }
];
Here is the DataTables definition:
<script type="text/javascript">
var dataSet = [
{ "name" : "Tiger Nixon",
"office": "London",
"scores" : 1 },
{ "name" : "Donna Snider",
"office": "New York",
"scores" : 2 },
{ "name" : "Airi Satou",
"office": "Tokyo",
"scores" : 3 }
];
$(document).ready(function() {
$('#example').DataTable({
dom: 'Bfrtip',
data: dataSet,
columns: [
{ title: "Name", data: "name" },
{ title: "Office", data: "office" },
{ title: "Score", data: "scores" }
],
rowCallback: function(row, data, index){
if(data.scores <= 1){
$(row).find('td:eq(2)').addClass("bg_red");
}
if(data.scores > 1 && data.scores <=2 ){
$(row).find('td:eq(2)').addClass("bg_yellow");
}
if(data.scores > 2){
$(row).find('td:eq(2)').addClass("bg_green");
}
},
buttons: [
{
extend: 'print',
//autoPrint: false, // useful for testing
exportOptions: {
//columns : [0,1,2,4],
columns : [ 0, 1, 2 ],
format: {
body: function ( inner, rowidx, colidx, node ) {
if (node.classList.contains('bg_red')) {
return '<span class="bg_red">' + inner + '</span>';
} else if (node.classList.contains('bg_yellow')) {
return '<span class="bg_yellow">' + inner + '</span>';
} else if (node.classList.contains('bg_green')) {
return '<span class="bg_green">' + inner + '</span>';
} else {
return inner;
}
}
}
},
customize: function ( win, butt, tbl ) {
$(win.document.body).find('span.bg_red').parent().css('background-color', 'red');
$(win.document.body).find('span.bg_yellow').parent().css('background-color', 'yellow');
$(win.document.body).find('span.bg_green').parent().css('background-color', 'green');
}
} ]
});
});
</script>
And here is the print-preview:
This uses the same technique as described in the other answer I mentioned in my comments, but adapted for your specific scenario. The reason it works is the same as described in that answer.
Update
You may need to adjust printer settings to see the colors on an actual print-out. For example, using Google Chrome:

Related

Mongo db query | Join | Create query on two collection

Select leadId count on two collection in Mongo DB
Collection 1 : leads
{
leadId:"abc123",
status:"OPENED",
stage:"start",
crossSell:
{
cc:
{
consent:true,
shown:[{first:true}]
}
}
}
Collection 2 : pdata
{
activeLeadId:"abc123",
status:"OPENED",
details:
[
{
rating:10
},
{
rating:9
}
]
}
Question : Find leadId count from leads collection join with pdata collection based on below conditions
leads.leadId = pdata.activeleadId and
leads.status = "OPENED" and
leads.crossSell.cc.consent = true and
leads.crossSell.cc.shown[0].first = true and
pdata.details.rating >= 5
You can try a aggregation query,
$match your conditions for leads collection
$lookup with pdata collection, pass leadId to match with pdata
match required conditions for pdata
$limit to return single document, because we don't need that data in response
$match condition to check is pdata is not empty
$count to get total number of records
db.leads.aggregate([
{
$match: {
status: "OPENED",
"crossSell.cc.consent": true,
"crossSell.cc.shown.first": true
}
},
{
"$lookup": {
"from": "pdata",
"let": { "leadId": "$leadId" },
"pipeline": [
{
$match: {
$expr: { $eq: ["$$leadId", "$activeLeadId"] },
"details.rating": { $gte: 5 }
}
},
{ $limit: 1 }
],
"as": "pdata"
}
},
{ $match: { pdata: { $ne: [] } } },
{ $count: "count" }
])
Playground

vue-good-table custom sorting

I am using vue-good-table and have the following code so far:
<vue-good-table :columns="columns" :rows="rows"
styleClass="vgt-table condensed striped bordered"
:sort-options="sortOptions"
:search-options="searchOptions"
:select-options="selectOptions"
#on-selected-rows-change="selectionChanged">
</vue-good-table>
sortOptions: {
enabled: true,
initialSortBy: { field: "date", type: "desc" },
}
columns() {
return [
{
label: "Name",
field: "name",
},
{
label: "CreationDate",
field: "date",
type: "date",
formatFn: function (value) {
return value != null ? moment(value).format('YYYY-MM-DD') : null;
},
sortFn(x, y) {
x = moment(x);
y = moment(y);
return x.unix() < y.unix() ? -1 : x.unix() > y.unix() ? 1 : 0;
},
},
]
}
Sorting works fine so far, and there are three states: 'asc', 'desc' and 'none'.
However i would like to achieve the following:
When clicking the column header and the current sorting type is 'none' for any of the columns, i would like to have the data sorted as defined in the initialSortBy property in the sortOptions. So sorted by date in desc order.
I tried using the #on-sort-change event but don't really know how to proceed further as i am quite new to Vue.
onSortChange(params) {
console.log('on-sort-change:');
console.log(params[0].field)
console.log(params[0].type)
if (params[0].type == 'none') {
console.log("default sort")
//TODO sort data as defined in initial sort
}
}

Thousands separator is not applied

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.

How DataTables determine columns type

I have a dynamic table enhanced by jQuery DataTables, which display a custom object similar to this example.
JSON:
{
"data": [
{
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": {
"display": "SomeString",
"timestamp": 1303686000
},
"office": "Edinburgh",
"extn": "5421"
},
// ... skipped ...
]}
JavaScript:
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: {
_: "start_date.display",
sort: "start_date.timestamp"
} },
{ data: "salary" }
]
} );
} );
The difference is that I dynamically build the columns configuration, because the columns can be in any order, and others columns can be added or removed from the list. For this example (my case is very similar) the problem is that for some reason the timestamp property is ordered as a String instead of being ordered as a number.
I discovered that after setting the column "type" as "number" the ordering works perfectly. I'm presuming that DataTables is auto detecting the column as "String" for some reason (maybe because the display element is a string).
How does DataTables set the type of the columns, when is not explicitly declared?
Edit 1
I made a sample code to show the problem
http://jsfiddle.net/Teles/agrLjd2n/16/
jQuery DataTables has built-in mechanism for type detection. There are multiple predefined functions for various types with fallback to string data type.
It's also possible to use third-party plug-ins or write your own.
There are multiple ways to specify data type, below are just the few.
SOLUTION 1
Use type option.
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: "start_date.display", type: "date" },
{ data: "salary" }
]
} );
} );
SOLUTION 2
Use returned JSON data for type detection, see columns.data for more information.
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: {
_: "start_date.display",
sort: "start_date.timestamp",
type: "start_date.timestamp",
} },
{ data: "salary" }
]
} );
} );
DataTables always check the "type" property of the column "data" to auto detect the type of the column, if no "type" property is specified it will check the default value "_".
So if you want DataTables to auto detect the type of the column checking the type of your "sort" property you should set the "type" property of data to be equals to your "sort" value
Here is a sample code with different approchs to achieve what I was tryng to do. Thanks #Gyrocode.com and #davidkonrad.
var Cell = function(display, value) {
this.display = display;
this.value = value;
}
$(document).ready(function() {
var cells = [
new Cell("120 (10%)", 120),
new Cell("60 (5%)", 60),
new Cell("30 (2.5%)", 30)
];
$('#example').DataTable( {
data: cells,
columns: [
{
title : "Column NOT OK",
data: {
_: "display",
sort: "value"
}
}, {
type : "num",
title : "Column Ok setting column type",
data: {
_: "display",
sort: "value"
}
}, {
title : "Column Ok changing default value",
data: {
_: "value",
display: "display",
filter: "display"
}
}, {
title : "Column Ok setting data type",
data: {
_: "display",
sort: "value",
type: "value"
}
}, {
type : "num",
title : "Column Not OK",
data: "display"
}
]
} );
} );

dataTables make <tr> clickable to link

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;
}