I have a datatable, I want to color code the column based value in the last row.
If the TYPE value is "O" then apply yellow color, otherwise nothing. My columns are dynamic.
expected result:
var dt= $(element).dataTable({
deferRender: true,
destroy: true,
"aaData": data, // data is coming from service
"aoColumns": columns // column is dynamic
});
SOLUTION
You can use drawCallback to handle table draw event and enumerate columns data with columns().every() to find columns containing required values and highlight them.
var table = $('#example').DataTable({
drawCallback: function(){
var api = this.api();
api.columns().every( function () {
var data = this.data();
if($.inArray('O', data) !== -1){
$(this.nodes()).addClass('highlight');
} else {
$(this.nodes()).removeClass('highlight');
}
});
}
});
Please note that the code above detects O in all rows. To handle only the last row you need to add more code.
DEMO
See this jsFiddle for code and demonstration.
Use the rowCallback
$(element).dataTable({
"rowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
switch(aData[0]){
case 'O':
$(nRow).css('backgroundColor', 'yellow');
//also style other rows here
break;
}
}
});
Simple demo: Fiddle
Related
I have a table in which I can edit and modify each cell.
I would like to highlight the cell that I modified.
At the moment I can only highlight the entire row but I don't have what I want to do.
I use createdRow to make the cells editable and get the modified row.
How can I do to highlight that modified cell?
var table = $("#deploymentMap_table").DataTable({
data: constructRaws(dataSet),//tbody
paging: false,
searching: false,
info: false,
fixedHeader: true,
scrollY: false,
scrollX: false,
responsive: false,
dom: 't', //display only the table
order: [[ 0, 'asc' ]],//order by 'service' col
columnDefs:[
{
targets:'_all',
render:function(data){
if(data == null) {return ""
} else {return data;}
}
},
{ targets: [0,1], "width" : "200px"},
],
columns: constructColumns(dataSet),//thead
dom: 'Bfrtip',
// attribute classname (background color) for services
rowCallback: function(row, data, index){
if ( data.code == 1 ) {
$('td', row).each( function ( value, index ) {
if($(this).contents().first().text()){
$(this).addClass('td_colorCD');
}
} );
}
$(row).find('td:eq(0)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$(row).find('td:eq(1)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$.each(row.childNodes, function(i,value){
if(value.innerText == "NoUP"){
$(value).addClass('td_colorBSF');
}
else if(value.innerText){
$(value).addClass('td_color');
}
})
},
// Make all cell editable
createdRow: function(row, data, dataIndex, cells) {
console.log(cells);
let original
row.setAttribute('contenteditable', true)
row.setAttribute('spellcheck', false)
row.addEventListener('focus', function(e) {
original = e.target.textContent
})
row.addEventListener('blur', function(e) {
if (original !== e.target.textContent) {
$('td', row).removeClass();
$('td', row).addClass('td_color_change');
const r = table.row(e.target.parentElement)
r.invalidate();
var lign = e.target.innerText;
lign = lign.split('\t');
var nRow = $('#deploymentMap_table thead tr')[0].innerText;
head = nRow.split('\n\t\n');
var newAR = mergeArrayObjects(head, lign);
console.log("newAR", newAR);
$(dataSet).each(function( index, values ) {
if(newAR.service[0].Services == values.service_name){
delete values.regions;
values.regions = newAR.region;
console.log(values);
}
})
console.log("dataset", dataSet);
}
})
}
});
I think the easiest way to handle this is to replace your rowCallback with a DataTables delegated event.
Below is a simple example which would change the color of a specific cell when you leave that cell:
Step 1) The onblur event requires the cell to have a tabindex attribute. You can add this however you wish - but here is one way, in your existing code:
$.each(row.childNodes, function(i,value){
$(value).attr('tabindex', i); // this line is new
// your existing code goes here
})
Note - this could be improved as it repeats tab indexes across rows. But it illustrates the approach.
Step 2: Add a new onblur event listener, after the end of your DataTable definition:
$('#deploymentMap_table td').on('blur', function () {
this.classList.remove("td_color");
this.classList.add("td_color_change");
} );
Step 3: The above code would need to be enhanced to include your edit-checking logic, which checks for an actual cell value change.
You can get the "before" cell values using this:
table.cell( this ).data();
And the "after" cell values using this - which gets the value from the HTML table (the DOM node), not from DataTables:
table.cell( this ).node().textContent;
The updated listener would be something like this:
$('#deploymentMap_table td').on('blur', function () {
var cellValueStart = table.cell( this ).data();
var cellValueEnd = table.cell( this ).node().textContent;
//console.log( cellValueStart );
//console.log( cellValueEnd );
if (cellValueEnd !== cellValueStart) {
table.cell( this ).data(cellValueEnd);
this.classList.remove("td_color");
this.classList.add("td_color_change");
}
} );
The table.cell( this ).data(cellValueEnd) command updates the cell in DataTables so that it matches the value you typed into the HTML cell. If you do not do this, then the data in the DataTables object (behind the scenes) will be out-of-sync with the data in the HTML table (what you see on your screen).
Warning: This approach is basic. It does not cover the case where a user may do the following:
Edit a cell from "A" to "B".
Leave the cell, so it is highlighted.
Return to the cell and edit it back from "B" to "A".
Leave the cell again.
In this case, the cell will remain highlighted.
One way around this is to capture the original state of every cell when you first load the table - and then check each edit against the value in the original data. This can be done, if needed - but is outside the scope of this question. But it also depends on what you need to do with the data, after you have finished editing it. If this is important to you, then it may be worth asking a new question for that specific problem.
I am trying to draw a table using D3 and also using DataTable() for other functionalities like sorting the columns, overall table search etc. But I am not able to go along with DataTable. I have dynamic data coming which I will have to populate in the table dynamically(extra rows addition). For this, I delete the entire table everytime I am tabulating the table. I am able to do it with normal d3 table, but when I try to use the DataTable, it throws the below error.
I have a drop-down menu from which user can select any item. listen_change listens for such a change and draws the table with data corresponding to that item which I fetch using ajax from DB. DB keeps getting updated from somewhere else.
I want to know a way to use DataTable without reinitialising it (as the error alert tells) for my dynamic table. Any help would be appreciated. Thanks in advance.
I am getting the following alert,
DataTables warning: table id=table_id - Cannot reinitialise
DataTable. For more information about this error, please see
http://datatables.net/tn/3
The Javascript part of the code is:
function listen_change() {
var timeOutId = 0;
document.getElementById('select_item').addEventListener('change',function() {
var e = document.getElementById("select_item");
var item_name = e.options[e.selectedIndex].text;
clearTimeout(timeOutId);
(function worker() {
$.ajax({
url: '/my_url/' + item_name + '/',
success: function(data) {
//delete_table(table_id)
table_data(data)
},
complete: function() {
// Schedule the next request when the current one's complete
timeOutId = setTimeout(worker, 3000);
}
});
})();
});
}
function table_data(data){
//puts data in the format required to draw D3 table
tabulate(table_id, data, columns)
}
function tabulate(container, data, columns){
var table = d3.select(container).attr("width",1)
var thead = table.append('thead')
var tbody= table.append('tbody')
var headers = thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) {
return column;
})
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(data)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column,id) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.attr("style", "font-family: Arial") // sets the font style
.html(function(d) {
return d.value;
});
$(document).ready(function(){
var o_table = $('#table_id').DataTable({
'bSort': true,
'bFilter': true,
"autoWidth":true,
"scrollY": "600px",
"scrollCollapse": true,
"info": true,
"paging": true,
"bLengthChange" : true,
"iDisplayLength":60,
"aLengthMenu" : [30,60,100],
});
})
return table;
}
The html part is:
<div>
<table class="table table--bordered table--highlight" align='center' cellspacing=50 cellpadding=20 id="table_id">
</table>
</div>
<script type="text/javascript">
$(document).ready(function(){
listen_change();
});
</script>
UPDATE 1
I tried giving 'bDestroy' : true in DataTable()and I am clearing data inside the table using $('table_id').empty(). This helps me in destroying the DataTable instance and helps me replace the table and thus the data changes dynamically. But, this brings me to a new problem now. I am updating the table every 3 seconds as mentioned in the code. Now, if user tries to search for anything using the search option, it works but after 3 seconds, the whole table comes up back. How to update the data dymanaically without affecting the search feature? Any help would be appreciated. Thanks in advance.
I have a web application where you can drag and drop pictures into boxes. If you drop it in the one it will add the picture's information to the datatable, if you drop in the left it will remove the data from the datatable. I was wondering If there was a way I could remove the row based on the id?
$('#pictures')
.dataTable({
"columnDefs": [{
"orderable": false,
"targets": 1
},
{
"orderable": false,
"targets": 3
}
]
});
var t = $('#pictures')
.DataTable();
$("#left")
.droppable({
accept: ".draggable",
drop: function (event, ui) {
console.log("drop");
$(this)
.removeClass("border")
.removeClass("over");
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped)
.detach()
.css({
top: 0,
left: 0
})
.appendTo(droppedOn);
var $id = $(this)
.children()
.last()
.attr('id');
var rowId = pictures[id].id;
t.row(pictures[$id].id)
.remove()
.draw(false);
}
});
This obviously isn't the entire thing; however, I think this is enough to identify any problems.
You can use DataTable's API to remove the corresponding row:
t.row("your selector here").remove().draw();
in row() you could use several kind of selectors. If you saved the row's id in a variable, simply use
t.row("#"+rowId).remove().draw();
Note that you have to call draw() after a remove, since datatables doesn't redraw itself after a remove due to performance reasons.
$('#pictures').DataTable().row("#YourRowId").remove().draw();
If the item you want to delete is the parent window;
window.parent.$('#pictures').DataTable().row("#YourRowId").remove().draw();
If you want to delete all the rows;
$('#pictures').DataTable().row().remove().draw();
You should pay attention to the JS version.
var table1= $('#TableID').DataTable({
"createdRow": function (row, data, dataIndex) {
var rowID = "row_" + data[0];
$(row).attr('id', rowID);
}});
var rowID = "#row_" + any format that follows as per your row ID; table1.row(rowID).remove().draw();
This will work for everyone. Here, in "createdRow" callback of the DataTable constructor, you can define all the data based styling that you want on your DataTable. I Have defined a row ID to be assigned to each row based on the value of the first column.
I have initialised a simple Datatable:
//initialise table
var dataTable = $('#example').DataTable({
searching: false,
responsive: true
});
//hide unnecessary columns
dataTable.columns(1).visible(false);
dataTable.columns(2).visible(false);
dataTable.columns(3).visible(false);
dataTable.columns(4).visible(false);
dataTable.columns(5).visible(false);
dataTable.columns(6).visible(false);
dataTable.columns(7).visible(false);
dataTable.columns(8).visible(false);
It can contain any number of records but I would like to take the values from all of the columns (only 1 is displayed to the user) and insert them into input fields (which may or may not be visible). I have successfully been able to select the rows using:
$('#example tbody').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
}
else {
dataTable.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
}
});
I have been looking into the Datatables API, row(), cells() etc and whilst I can view the data() method I simply can't see how to extract data from EACH cell on the row into the input text fields on the same webpage. I have also looked at fnGetSelectedData but I didn't get far as it always returned undefined via the console.
To explain the use case, it's essentially an Address Lookup. Each column in the table represents part of the address, I want to take the cells from the selected row and insert it into the form as a users selected address.
Any help is appreciated
SOLUTION
Use the code below to get data for the selected row:
var data = $('#example').DataTable().row('.selected').data();
Then you can populate your input fields as shown below:
$('#name').val(data[0]);
$('#email').val(data[1]);
See this jsFiddle for demonstration.
NOTES
You can simplify your initialization code:
var dataTable = $('#example').DataTable({
searching: false,
responsive: true
columnDefs: [
{
targets: [1,2,3,4,5,6,7,8],
visible: false
}
]
});
To get an object with the values use:
yourTableVariable.rows({ selected: true }).data();
Then you can do something like this to get specific value(example id):
yourTableVariable.rows({ selected: true }).data()[0].id;
I'm using the following code to initialize jQuery DataTables:
var oTable = $('#qpidvulh_to-do_list').dataTable( {
"columns": [
{
"data": "item",
"className": "editable"
}
]
} )
The issue with this code is that it adds the editable class to the th of each column, even though I only want it added to the td of each column.
How can I get the code to only add the editable class to the cells of each column and not their headers?
Thanks to mainguy and markpsmith for posting their answers. I'll throw my own solution into the mix, but I'd still like to see what everyone thinks the best performing solution would be:
$('#qpidvulh_to-do_list thead th').removeClass('editable');
Use this to add the class to the cell, 100% working solution, make sure the you give the correct target number while adding the class, here createdCell function adds class to the targeted cell,
var oTable = $('#<?php echo $module; ?>').DataTable({
columnDefs: [{"orderable": true, "targets": 1,
'createdCell': function (td, cellData, rowData, row, col) {
$(td).addClass('myclass');
// $(td).parent('tr').attr('data-id', rowData[0]); // adds the data attribute to the parent this cell row
}
}]
});
I had this problem but the suggested solution didn't really work for me because I am applying different types of inputs (number, text) selectively to cells in multiple tables. I have an onclick event for the cell to convert it into an editable box. I changed where it is called from
table.on('click', '.edit-text', function() {
// yadda yadda;
}
to
table.on('click', 'td.edit-text', function() {
// yadda yadda;
}
In this way the function ignores the 'th' cells with that class.
EDIT:
A second way I have found is to use the createdCell option in the columns definition:
columns: [
{
data: 'property_name',
createdCell: cell => $(cell).addClass('some-class')
}
]
Why not simply use jquery?
$("td").addClass('editable');
Look here
Update: On second thought: It would be better to put this jquery snippet in the draw event of dataTables so it works too when pagination changes and the table is redrawn.
You can use fnRowCallback for this:
var oTable = $('#qpidvulh_to-do_list').dataTable( {
"columns": [
{
"data": "item"
}
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$(nRow).children().each(function (index, td) {
$(this).addClass('editable');
});
}
"aoColumns":[null,{sClass:'editable'},null,null,{ "sClass": 'my_class other_class' }]
In my table I put the editable in the draw callback like this:
$('#table td.editable-class').editable();
and in the column defs I gave the editable cells a class. Here's an example:
var table = $('#blocks').dataTable({
ajax: {
url: ...
},
columns: [
{ data: "column_data", "name": "column1", visible: false },
{ data: "editable_column", class: "editable another-class" }
],
"drawCallback": function ( settings ) {
$('#table td.editable').editable();
}
});
Hope that helps.
The best way will be using CSS.
Just set the CSS class selector to affect the 'td' and not the 'th'.
Try this code:
td.editable {
color: red; /*Or some other attribute*/
}
Important: With this solution the 'th' element will still have the 'editable' class set, but it wont be affected by the CSS styling.
If you still need to remove the class on the 'th' element try this:
$('#qpidvulh_to-do_list th').removeClass('editable');
/* ADDITIONAL INFO */
If you need more info about CSS selectors, try this page:
https://www.w3schools.com/cssref/css_selectors.asp