DataTables: Add class to table cells, but not table headers? - javascript

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

Related

Change color of a cell after editing in datatable

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.

How to add a class based on the cellData Key in createdCell callback in datatables

I have a requirement to add a class based on the column Key in the cell in data tables. I have tried using createdCell callback but it contains the cell data but not the cell data source which contains the key.
columnDefs: [
{
targets: '_all',
createdCell: function(cell, cellData, rowData, row, col) {
if(Object.keys(modifiedColumns[row]).length){
console.log(col, cellData);
}
}
}
],
Here, I have keys of the cell in modifiedColumns for each row on which I need to add class.
These keys would be different for each row.
you can use the render function.
$('#example').dataTable( {
"columnDefs": [ {
"targets": 0,
"data": "download_link",
"render": function ( data, type, row, meta ) {
return 'Download';
}
} ]
} );
you can add classes here also.
more info from this link
Objective:
To add class names to the cells in each column, where the cell names are provided in an array. In your example, the array is called modifiedColumns. I assume it looks something like this:
var modifiedColumns = ['zero_class', 'one_class', 'two_class'];
So, in this case, all the cells in column index zero (i.e the first column) need to have zero_class added as a class name:
<td class="zero_class">...</td>
Approach:
To add class names to your table's <td> tags, you can use the DataTables node() function.
To know what the column index is for a specific <td> tag, you can use the DataTables cells().every() function.
We can combine these as follows:
<script type="text/javascript">
var modifiedColumns = ['zero_class', 'one_class', 'two_class'];
$(document).ready(function() {
var table = $('#example').DataTable( {
// your initialization here
} );
for (var i = 0; i < modifiedColumns.length; i++) {
table.cells().every( function (rowIdx, colIdx) {
if (colIdx < modifiedColumns.length) {
$(this.node()).addClass( modifiedColumns[colIdx] );
}
} );
}
} );
</script>
Notes:
We assign the table to a variable: var table = $('#example').DataTable( {.
We use that variable in a separate for loop, following (and outside of) the table definition.
The every function has access to the row index and column index for each cell - so we use that to look up the required class name from our modifiedColumns array.
You cannot use the render function to do this, as that function only provides access to the data inside a cell - and not to the cell (i.e. the node) itself.

jquery datatable whole column background color

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

how to change the content of a header cell in dataTables?

I'm using the dataTables plugin
On my sortable columns I want to replace the column text with a button.
However doing this:
$( oSettings.aoColumns[i].nTh).text();
I can retrieve the text of the respective column, BUT
$( oSettings.aoColumns[i].nTh).text("some text");
$( oSettings.aoColumns[i].nTh).html("<a href='#'>some button</a>");
Does not do anything.
Can somebody tell me why I can retrieve info from a cell but not edit it's content? Not necessarily a dataTables question, but maybe someone has run into something similar.
Thanks for help!
EDIT: This is the solution:
Inside your table call specify, which columns should be sortable = these get a .jqmSorter class
"aoColumns": [
/* Select */ {"bSortable": false },
/* Type */ {"sClass": "jqmSorter"},
/* From */ {"bSortable": false },
/* Status */ {"bSortable": false },
],
Then call the fnHeaderCallback in which I'm replacing the header cell content with a JQM button:
"fnHeaderCallback": function( nHead ) {
$(nHead).closest('thead').find('.jqmSorter').each( function () {
var sortTitle = $(this).text(),
sortButton =
$( document.createElement( "a" ) ).buttonMarkup({
shadow: false,
corners: false,
theme: 'a',
iconpos: "right",
icon: "ui-icon-radio-off"
})
sortButton.find('.ui-btn-text').text(sortTitle);
$(this).html( sortButton )
sortButton.addClass("colHighTrigger");
});
}
You can do it this way:
While defining table columns (define if you not doing it already), and use the sClass attribute of the table column definition (which is in JSON).
After this, that class will be applied to the table column.
After this, use the callback function of datatables : fnRowCallback
and in this, set the html as
$(nRow, '.your_class').html('Your HTML Values');
This will be called when each row of the table is rendered.
If you don't want it to do on each row, you can control that with an if-condition.
Use fnRender in your aoColumns settings, use it to return HTML code for that specific cell, drop downs, checkboxes, anything you want will work there.
"aoColumns": [
/*Col 1*/
{
"mData": "RowID",
"bSortable": false,
"sClass": "jqmSorter",
"fnRender": function(obj){
return "<input id='" + obj.aData.RowID + "' type='button' value='myval'/>"
}
},
/*Col 2*/
{
"bSortable": false,
"sClass": "jqmSorter",
"fnRender": function(obj){
return "<input id='" + obj.aData.RowID + "' type='button' value='myval'/>"
}
}
]

jQuery DataTables: How do I add a row ID to each dynamically added row?

Summary
I am using the great dataTables jQuery plugin from http://www.datatables.net. In my script, I am dynamically adding rows based on an event firing using fnAddData. Using fnRowCallback, I add in a unique row ID. This sometimes fails and does not add a row ID. In a test of 46 row additions, usually 6 to 8 rows do not get a row ID.
Add Row function
function ps_ins(row)
{
var rowArray = row.split('|');
row = rowArray;
var alarmID = parseInt(row[1],10);
$('#mimicTable').dataTable().fnAddData([
alarmID, 'col2', 'col3', 'col4',
'col5', 'col6', 'col7'
]);
}
Rows are added to the table correctly. The test I am running adds 46 rows, and all appear as expected.
Add the row ID
I am trying to add a unique ID to each row so I can later modify a specific row and refer to it in dataTable's cache using a combination of fnGetRows and .filter.
I am doing this using fnRowCallback during the initialisation stage. I've kept all the other settings just incase there's anything there that might have an impact on the problem.
$('#mimicTable').dataTable({
"sDom": 'lip<"mimicSpacer">f<"numUnAck">rt',
"sScrollY": "365px",
"aaSorting": [[4,'desc'],[5,'desc']],
"iDisplayLength": 15,
"aLengthMenu": [[15, 50, 100, -1], [15, 50, 100, 'All']],
"bAutoWidth": false,
"aoColumns": [
null,
{ "sWidth": "20%" },
{ "sWidth": "22%" },
{ "sWidth": "9%" },
{ "sWidth": "9%" },
{ "sWidth": "20%" },
{ "sWidth": "20%" }
],
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$(nRow).attr("id",'alarmNum' + aData[0]);
return nRow;
}
});
A console.log of the dataTable object shows:
As you can see, #14 has the row id and also the correct rowStripe class. #15 (and onwards) doesn't.
So, why is fnRowCallback not firing each time a row is added, only sometimes? Maybe there is a better way to add a row ID when a row is added?
Found the solution:
http://www.datatables.net/forums/discussion/2119/adding-row-attributes-after-fnadddata/p1
For anyone else wanting a quick solution, I did:
var addId = $('#mimicTable').dataTable().fnAddData([
alarmID,
'col2',
'col3',
'col4',
'col5'
]);
var theNode = $('#mimicTable').dataTable().fnSettings().aoData[addId[0]].nTr;
theNode.setAttribute('id','alarmNum' + alarmID);
I know this is quite an old thread, but this might help others.
The easiest way I do it to add id attribute to the last added row as soon as I called the data table function fnAddData is:
$('#table').dataTable().fnAddData( ['col1','col2','col3'] );
$('#table tr:last').attr('id','col'+row_id);
Try this it worked for me nicely:
var newRow = oTable.fnAddData( [ etc..]);
var oSettings = oTable.fnSettings();
var nTr = oSettings.aoData[ newRow[0] ].nTr;
nTr.id = 'new id';
There is something unexpected with your code in the jsbin, even if it appears to be working. It initializes with the "browsers" data set. Then it clears. Then it makes a new table with one row. Then it clears. Then it makes a new table with two rows. Then it clears. Then it makes a new table with three rows.
I'd have to get a better sense of the code sample and its end goal (and alas my attention is diverted elsewhere right now) but you should be aware that fnRowCallback SHOULD be the way to do this, and that there are many redundant table constructions and row additions that are going to impact performance as well as flexibility with modifying rendering in the future.
You can use DT_RowId when you add new row, and use object instead an array, see below:
$('#mimicTable').dataTable().fnAddData({
'DT_RowId': alarmID, 0:'col2', 1:'col3', 2:'col4',
3:'col5', 4:'col6', 5:'col7'
});
This worked for me
var MyUniqueID = "tr123"; // this is the uniqueId.
var rowIndex = $('#MyDataTable').dataTable().fnAddData([ "column1Data", "column2Data"]);
var row = $('#MyDataTable').dataTable().fnGetNodes(rowIndex);
$(row).attr('id', MyUniqueID);

Categories

Resources