Add new value and remove previously added value in an array (Javascript) - javascript

I'm currently using the DataTables plugin for my project.
I have an AJAX sourced datatable where you can only ever have one row selected, now because my datatable is done server-side I need to keep track of which one is selected when changing pages.
Therefore I have been using this solution but this only seems to work for multiple row selection
Now essentially what I want to happen is, when you select a new row it should add the new row id to the array but also remove the previously added row id from the array, so there should only ever be one result in the array at a time.
Visually for better understanding:
var selected = []
Click Row 1 after loading table = [row_1]
Click Row 2 removing row_1 and adding row_2 = [row_2]
var selected = [];
$("#example").DataTable({
"processing": true,
"serverSide": true,
"ajax": "scripts/ids-arrays.php",
"rowCallback": function( row, data ) {
if ( $.inArray(data.DT_RowId, selected) !== -1 ) {
$(row).addClass('selected');
}
}
});
$('#example tbody').on('click', 'tr', function () {
var id = this.id;
var index = $.inArray(id, selected);
if ( index === -1 ) {
selected.push( id );
} else {
selected.splice( index, 1 );
}
$(this).toggleClass('selected');
} );

Instead of adding an element to the array, you could replace the whole array. It seems a bit wasteful to use an array to store a single element, but there you go.
selected.push( id );
becomes
selected = [id];

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.

DataTable JQuery How to remove a row from a table based on an ID?

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.

jQuery DataTables iterate over rows and change cell background

I am trying to iterate over all cells in a column (column index 1) in a DataTable and change the background color based on cell value using the following code:
var table = $('#my_table').DataTable( {...});
console.log("next, iterate over rows in table: "+table);
table.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
console.log("looping over rows");
var cell = table.cell({ row: rowIdx, column: 1 }).node();
if (cell.data() == 'mouse'){
$(cell).css('background-color', 'orange');
}
});
console.log("finished iterating over rows ");
The table is displaying the data fine.
However the console log prints:
>>next, iterate over rows, table: [object Object]
>>finished iterating over rows
ie the
table.rows().every( function (...){...}
is not entered. I copied and pasted from DataTables examples and I have no idea why it is not being executed.
The only thing I can think of is that the DataTables docs here: https://datatables.net/reference/api/rows().every() mention- Iterate over each selected row. None of the rows in the table are selected, I just want to loop through every row (and change cell color) regardles if it is selected or not.
Note I also tried:
table.rows().eq(0).each( function ( index ) {
var row = table.row( index );
var data = row.data();
console.log(data)
});
And this is not executed either (console.log doesn't print anything from inside the function).
You can iterate over the table's td elements and capture the text content of each cell.
Apply some logic to these and you can easily assign each cell's background colour.
I have used arr.map() as it's ES6 JavaScript, but .each() works too.
$('table td').map(function(i, cell) {
var cellContent = $(cell).text();
console.log(i,cellContent); // for demonstration
if (cellContent === 'pending') $(cell).css('background-color', '#ccc');
});
This can be easily changed to get the cell element's data, class, or id too.

DataTable does not re-draw after updating rows

I'm using the DataTables library to create a table with extra functionality. What I'd like to achieve, is that the user can select rows and then press a button. This will call the server, do some stuff and the rows should be updated accordingly.
However, after I'm done iterating over the rows to be changed and setting its values, re-drawing the table does not actually update its values. I update the data object, invalidate the cache and call table.draw(). It's very similar to the last example on this page.
I have created a JSFiddle of this issue. The button updates the date objects of the selected rows and the table is re-drawn, but the data inside the table is not updated. The core JS code:
$('#updateRow').click(function() {
//Get the table
var table = $('#example').DataTable();
//Iterate over selected rows
var rowData = table.rows({
selected: true
}).every(function() {
//For every selected row, update startDate
var d = this.data();
d.startDate = "01/01/2017";
console.log('Set startDate of ' + d.name + ' to ' + d.startDate);
//Invalidate the cache
this.invalidate();
});
//Re-draw the table
table.draw();
});
I forked and did the solution from your JsFiddle. Here's the relevant snippet from fiddle https://jsfiddle.net/k38r9be5/1/
var rowData = table.rows({
selected: true
}).every(function(rowIdx) {
var colIdx = 4; // startDate is the fifth column, or "4" from 0-base (0,1,2,3,4...)
table.cell( rowIdx, colIdx).data('01/01/2017').draw();
});
Basically, via the API you can get the cell object itself, and modify the contents with .data(). In your version you weren't actually getting a particular cell object and instead just copied the data contents of the row to a variable, and modified that.

multiple data table toggle column

$(document).ready(function() {
var table = $('#example').DataTable( {
} );
var table = $('#example2').DataTable( {
});
$('input.toggle-vis').on( 'click', function (e) {
// e.preventDefault(); //empĂȘche la mise Ă  jour des check
// Get the column API object
var column = table.column( $(this).attr('data-column') );
// Toggle the visibility
column.visible( ! column.visible() );
} );
} );
My event "input.column-toggle" works only for my last table (example2) ...
How can I do for the event work for all my a.column-toggle class ?
You're using the table variable to find the column inside the table. But you've assigned two things (example1 and example2) to the same variable in successive statements. Therefore example2 has replaced example1 in the table variable. You've lost the information that relates to example1.
You need two variables, table1 and table2. And then perform the column hiding operation on both.
e.g. something like (I haven't tested it):
$(document).ready(function() {
var table1 = $('#example').DataTable( {
} );
var table2 = $('#example2').DataTable( {
});
$('input.toggle-vis').on( 'click', function (e) {
// Get the column API object
var column1 = table1.column( $(this).attr('data-column') );
var column2 = table2.column( $(this).attr('data-column') );
// Toggle the visibility
column1.visible( ! column1.visible() );
column2.visible( ! column2.visible() );
} );
} );
Or, if you need to do this on several tables, or want to add more tables flexibly in future, you might want to consider creating an array of tables and then looping through the array, performing the same actions on each element.

Categories

Resources