There are quite some answers to be found about moving rows between two datatables.
(DataTables move rows between tables).
However, doing that between one datatable and one plain DOM table has proven to be quite the struggle.
I have one Datatable:
var colcount = $("#uitschrdiv").children("thead > tr:first").children().length;
dtable = $("#uitschrdiv").dataTable({
"oLanguage": {
"sUrl": "/css/datatables/nl.txt"
},
"aoColumnDefs": [
{ "bSortable": false, "aTargets": [colcount - 1] }
],
"iDisplayLength": 25,
"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "Alles"]],
"sPaginationType": "full_numbers",
"bStateSave": true,
"iCookieDuration": 60 * 30 /* 30min */
});
I have one normal DOM table named #inschrdiv
each of them has a button in the last td to move the row to the other table.
How to switch tr's between the two of them?
before I switched one of the tables to a datatables, this was the jQuery that would move the TR's
$(".uitschrbut").live("click", function () {
if ($(this).hasClass("inactivebtn")) {
//werkt niet
return false;
} else {
$(this).removeClass("uitschrbut").addClass("inschrbut").val("inschrijven");
$("#uitschrdiv").append($(this).parent().parent());
checkInEnUitschrMax();
}
});
$(".inschrbut").live("click", function () {
if ($(this).hasClass("inactivebtn")) {
//werkt niet
return false;
} else {
$(this).addClass("uitschrbut").removeClass("inschrbut").val("uitschrijven");
$("#inschrdiv").append($(this).parent().parent());
checkInEnUitschrMax();
}
});
this does not at all work with Datatables.
The solution took me a while before I understood that Datatables can only work with DOM objects on removing/adding and doesn't handle jQuery objects.
This is what I ended up with:
$(".uitschrbut").live("click", function () {
if ($(this).hasClass("inactivebtn")) {
//werkt niet
return false;
} else {
$(this).removeClass("uitschrbut").addClass("inschrbut").val("inschrijven");
var jrow = $(this).parents("tr");
jrow.detach(); //you need to detach this because if the datatable has a filter applied in search, it will stay in this table until the filter fits the data in this row. It would only then be moved to the datatable.
dtable.fnAddTr(jrow[0]); //used plugin, see below, jrow[0] gets the DOM of jrow
checkInEnUitschrMax();
}
});
$(".inschrbut").live("click", function () {
if ($(this).hasClass("inactivebtn")) {
//werkt niet
return false;
} else {
$(this).addClass("uitschrbut").removeClass("inschrbut").val("uitschrijven");
var row = $(this).parent().parent()[0]; //the [0] gets the native DOM elem
$("#inschrdiv tbody").append(row); //append the DOM element to the other table
dtable.fnDeleteRow(row); //delete this row from the datatable
checkInEnUitschrMax();
}
});
You will need the plugin fnAddTr which can be found here: http://datatables.net/plug-ins/api#fnAddTr
If you want to add more than one row at once you can use this plugin that allows you to apparently add whole DOM tables at once into a datatable: http://datatables.net/forums/discussion/comment/31377#Comment_31377
Related
I duplicated my thead row for custom column search according this example
Problem is that I have fixed columns 0 and 1 from left. When I perform scroll right, second row which contains input for column filter is moving but the rest of column is sticky.
As I see css, that tr element is missing sticky position as the rest of fixed columns.
How to fix it?
this is my code
$('#custom_list_details thead tr').clone(false)
.addClass('head_filters')
.appendTo('#custom_list_details thead');
custom_list_details_table= $('#custom_list_details').DataTable({
'order': [[1, 'asc']],
"orderCellsTop": true,
'fixedColumns': {
'left': 2
},
"select":true,
"keys": {
"columns": ':not(:first-child)',
"focus": ':eq(2)',
"blurable": false
},
'colReorder': {
'fixedColumnsLeft': 2
},
"ajax": '/customlist_table/'+$custom_list_id+'.json',
"processing": true,
'dom': 'lfr<"pull-right"B>tip',
'buttons': [
{"extend" : 'copyHtml5',"text":"Copy","className": 'btn btn-default btn-xs'},
{"extend" : 'excelHtml5',"text": "XLS","className": 'btn btn-default btn-xs'},
{"extend" : 'csvHtml5',"text": "CSV","className": 'btn btn-default btn-xs'},
{
text: 'Change table size',
className: 'btn btn-primary btn-xs table-size-btn',
action: function ( e, dt, node, config ) {
if ($('#custom_list_details').hasClass('compact') && $('#custom_list_details').hasClass('smaller-table-font'))
{ $('#custom_list_details').removeClass('compact smaller-table-font')}
else { $('#custom_list_details').addClass('compact smaller-table-font')}
}
}
],
"columnDefs": [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
"autoWidth":false,
"columns": $columns,
"pageLength": $user_profile_data.table_length,
'lengthMenu': [
[10, 50,100, -1],
[10, 50,100, "All"]
],
"columnDefs": [
{
'targets': 0,
'className': 'center-text',
'checkboxes': {
'selectRow': true
}
}
],
initComplete: function ()
{
$("th[data-column-index='1']").css("background-color","white")
$("th[data-column-index='0']").css("background-color","white")
var api = this.api();
api
.columns()
.eq(0)
.each(function (colIdx) {
if (colIdx > 0) {
// Set the header cell to contain the input element
var cell = $('.head_filters th').eq(
$(api.column(colIdx).header()).index()
);
$(cell).html('<input class="form-control" style="width:100%" type="text" placeholder="" />');
// On every keypress in this input
$(
'input',
$('.head_filters th').eq($(api.column(colIdx).header()).index())
)
.off('keyup change')
.on('keyup change', function (e) {
e.stopPropagation();
// Get the search value
$(this).attr('title', $(this).val());
var regexr = '({search})'; //$(this).parents('th').find('select').val();
var cursorPosition = this.selectionStart;
// Search the column for that value
api
.column(colIdx)
.search(
this.value != ''
? regexr.replace('{search}', '(((' + this.value + ')))')
: '',
this.value != '',
this.value == ''
)
.draw();
$(this)
.focus()[0]
.setSelectionRange(cursorPosition, cursorPosition);
});
}
else {
var cell = $('.head_filters th').eq(
$(api.column(colIdx).header()).index()
);
$(cell).html('');
}
});
custom_list_details_table.columns.adjust()
//column search end
}
});
here is fiddle with the issue, input search is not fixed
According to DataTables docs about FixedColums:
Additional complexity
It is important to state up front that utilising
FixedColumns in your DataTable can significantly increase the
complexity of the table and its use should not be undertaken lightly,
particularly for complex tables.
Based on that, I don't really know if it's possible to create a second header row and make it FixedColumns compliant, with the normal initialization options.
In Datatables' forum there's a question (a bit old indeed, made in 2016) about a problem with FixedColumns extension and multiple header rows, where the DataTable developer answers:
This ultimately is due to a limitation in DataTables in that you cannot construct complex headers using its initialisation options.
Maybee this kind of issue is still here after 6 years? Don't know :)
That said, I managed to get it work with standard jQuery's DOM manipulation.
I added this drawCallback() in the initialization options, to have column widths recalculated on each draw:
drawCallback: function () {
var api = this.api();
api.columns.adjust();
}
After the table initialization and before the end of $(document).ready() I added a function to get the left CSS value from the fixed cells of the first header row and pass them to the corresponding cells in the second header row:
function cssAdjust(table) {
// get the table header
const header = table.table().header();
// get the 'left' CSS declaration value for first_row-first_column 'th' cell
const col1_CSS_left = $(header)
.find('tr')
.eq(0) // first row
.find('th')
.eq(0) // first column
.css('left');
// apply the found value to the second_row-first_column 'th' cell
$(header)
.find('tr')
.eq(1) // second row
.find('th')
.eq(0) // first column
.css({ left: col1_CSS_left, position: 'sticky' });
// get the 'left' CSS declaration value for first_row-second_column 'th' cell
const col2_CSS_left = $(header)
.find('tr')
.eq(0) // first row
.find('th')
.eq(1) // second column
.css('left');
// apply the found value to the second_row-second_column 'th' cell
$(header)
.find('tr')
.eq(1) // second row
.find('th')
.eq(1) // second column
.css({ left: col2_CSS_left, position: 'sticky' });
table.draw(); // redraw the table
}
After that, always before the end of $(document).ready(), I added a window.resize listener, to avoid messing up widths of columns if the window is resized:
// add eventListener to window resize
window.addEventListener('resize', function () {
cssAdjust(custom_list_details_table);
});
cssAdjust(custom_list_details_table); // <= I immediately call the function to have the fixed double header also in the first table draw;
Here is a codepen with the code:
https://codepen.io/cheesyman/pen/NWXXdPO
In jquery datatable, single check box should be selected.
This link is working fine.
But above link is using jquery.dataTables 1.10.16 version. And I am using jquery.dataTables 1.9.4.
Can the same functionality as listed in example given above be possible with jquery.dataTables 1.9.4 instead of jquery.dataTables 1.10.16?
In the same page which you give the link, there are many explanation about to using "single check" oparetion.
At the end of the listed attachment, you can see the referanced .js file is
https://cdn.datatables.net/select/1.2.5/js/dataTables.select.min.js
In your page, you should add this file referance after dataTable.js.
I think, the version of jquery is not important. The important file is "dataTables.select.js"!
Secondly, you must update your dataTable maker codes like the sample below;
$(document).ready(function() {
$('#example').DataTable( {
columnDefs: [ {
orderable: false,
className: 'select-checkbox',
targets: 0
} ],
select: {
style: 'os',
selector: 'td:first-child' // this line is the most importan!
},
order: [[ 1, 'asc' ]]
} );
} );
UPDATES :
Why dont you try to write your own selector function?
for example;
$(document).ready(function() {
$('#example').DataTable( {
/// put your options here...
} );
$('#example').find("tr").click(function(){ CheckTheRow(this); });
} );
function CheckTheRow(tr){
if($(tr).find("td:first").hasClass("selected")) return;
// get the pagination row count
var activePaginationSelected = $("#example_length").find("select").val();
// show all rows
$("#example_length").find("select").val(-1).trigger("change");
// remove the previous selection mark
$("#example").find("tr").each(function(i,a){
$(a).find("td:first").removeClass("selected");
$(a).find("td:first").html("");
});
// mark the picked row
$(tr).find("td:first").addClass("selected");
$(tr).find("td:first").html("<i class='fa fa-check'></i>");
// re turn the pagination to first stuation
$("#example_length").find("select")
.val(activePaginationSelected).trigger("change");
}
Unfortunately, legacy data table does not support or have that select extension.
Workaround:
Create checkbox element inside 'mRender' callback.
Bind action to the checkbox. (This can be done inside the fnRowCallback or outside as in my example in below fiddle
https://jsfiddle.net/Rohith_KP/dwcatt9n/1/
$(document).ready(function() {
var userData = [
["1", "Email", "Full Name", "Member"],
["2", "Email", "Full Name", "Member"]
];
var table = $('#example').DataTable({
'data': userData,
'columnDefs': [{
'targets': 0,
'className': 'dt-body-center',
'mRender': function(data, type, full, meta) {
return '<input type="checkbox" value="' + $('<div/>').text(data).html() + '">';
}
}],
'order': [1, 'asc']
});
$('#example tr').click(function() {
if ($(this).hasClass('row_selected'))
$(this).removeClass('row_selected');
else
$(this).addClass('row_selected');
});
});
Also, I suggest you to upgrade your datatable version. Then you can use that select extension.
Can the same functionality as listed in example given above be possible with jquery.dataTables 1.9.4 instead of jquery.dataTables 1.10.16?
Yes.
But, not using the Select Extension since it requires at least version 1.10.7.
For 1.9.4, a possible solution would be:
$(document).ready(function() {
$('#example').find("td input[type='checkbox']").click(function() {
selectRow(this);
});
var table = $('#example').DataTable();
function selectRow(clickedCheckBox) {
var currentPage = table.fnPagingInfo().iPage;
// Being unchecked
if (!$(clickedCheckBox).is(':checked')) {
$(clickedCheckBox).removeAttr('checked');
getRow(clickedCheckBox).removeClass('selected');
return;
}
var selectEntries = $("#example_length").find("select");
var showEntriesCount = selectEntries.val();
var totalRows = table.fnGetData().length;
// If show entries != totalRows append total rows opiton that can be selected
if (totalRows != showEntriesCount)
selectEntries.append($('<option>', {
value: totalRows,
text: totalRows
}));
// Display all rows
selectEntries.val(totalRows).trigger("change");
// Removes all checked attribute from all the rows
$("#example").find("td input[type='checkbox']").each(function(value, key) {
getRow(key).removeClass('selected');
$(key).removeAttr('checked');
});
// Check the clicked checkBox
$(clickedCheckBox).prop('checked', true);
getRow(clickedCheckBox).addClass('selected');
// Re set the show entries count
selectEntries.val(showEntriesCount).trigger("change");
// If added, Remove the additional option added to Show Entries
if (totalRows != showEntriesCount)
selectEntries.find("[value='" + totalRows + "']").remove();
// Go to the page on which the checkbox was clicked
table.fnPageChange(currentPage);
}
function getRow(element) {
return $(element).parent().parent();
}
});
The above will require fnPagingInfo to take the user back to initial page. I haven't tested the solution on large dataset, tested it on a table with 150 rows, but should work fine on larger datasets too.
JSFiddle
Have you tried below code and I checked and it is working fine, you need to update styles and scripts:
You havr to update the latest styles and scripts to achieve latest functionality.
Single check box selection with jquery datatable
I am using a jquery datatables api index column. I've managed to make the table work by following the documentation shown on the page.
I also used the Buttons plugin to print the table, but in the "index" -- or in my case I named it "Bil" -- column, the numbers are not printed out.
The same problem occurs when I want to view the data after downloading the table in Excel and PDF.
The output when I wanted to print the table:
I don't know if it is a bug or not since I can't find the issue raised else where. I suspect the index value was only loaded to the page but is not inserted into the table. Is there a workaround to maybe use javascript to insert the value inside the table's ?
Here is the datatable's javascript that is responsible for the indexing:
//Datatable
var t = $('#tablePelajarLama').DataTable({
dom: 'lBfrtip',
buttons: [
'copy', 'excel', 'pdf', 'print'
],
"columnDefs": [ {
"searchable": false,
"orderable": false,
"targets": 0
} ],
"order": [[ 1, 'asc' ]]
});
//index counter
t.on( 'order.dt search.dt', function () {
t.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
cell.innerHTML = i+1;
} );
} ).draw();
On a side note, I use PHP to load the data into the table if it in any way affects the process. Thanks.
SOLUTION
You need to use cell().invalidate() API method to tell DataTables to re-read the information from the DOM for the cell holding the index.
t.on( 'order.dt search.dt', function () {
t.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
cell.innerHTML = i + 1;
t.cell(cell).invalidate('dom');
} );
} ).draw();
DEMO
See this jsFiddle for code and demonstration.
I have a datatable which when I click on a row, it highlights the row. I want to save the row index and use it to re-highlight that row when the page is reloaded.
var table = $('#example').DataTable( {
"ajax": "DataQueries/FetchOpenJobs.asp",
stateSave: true,
"aLengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]],
"iDisplayLength": 25,
"order": [[ 0, "desc" ]],
columnDefs: [
{"visible": false, "targets": [2,3]},
{"type": 'date-uk', "targets": [1,9,10] },
{"type": 'title-string', "targets": [11] }
],
} );
I am able to get the row index using the below:
var selectedRowIndex = table.row(this).index();
However, I am unsure as to how to re-highlight using the row index.
I think this question deserves a more thorough example.
I would save the selected id('s) in the localStorage as an stringified array. When the page is (re)loaded then retrieve the array and if it contains any stored indexes, highlight the corresponding rows. Below a code example in explanatory order :
Sample code of highlightning rows when they are clicked :
$('#example').on('click', 'tr', function() {
$(this).toggleClass('highlight');
processSelected(table.row(this).index(), $(this).hasClass('highlight'));
});
Basic code for maintaining an array of highlighted row indexes in the localStorage :
function processSelected(id, selected) {
if (selected) {
selectedRows.push(id);
} else {
selectedRows.splice(selectedRows.indexOf(id), 1);
}
localStorage.setItem('selectedRows', JSON.stringify(selectedRows));
}
When the page is loaded, retrieve the array from localStorage :
var selectedRows = JSON.parse(localStorage.getItem('selectedRows'));
Finally, re-highlight stored row indexes when the dataTable is initialised :
var table = $('#example').DataTable({
initComplete : function() {
if (!Array.isArray(selectedRows)) {
//selectedRows does not exists in localStorage or is messed up
selectedRows = [];
} else {
var _table = this.api();
selectedRows.forEach(function(index) {
//for some reason to$() doesnt work here
$(_table.row(index).node()).addClass('highlight');
})
}
}
});
demo -> http://jsfiddle.net/f3ghvz4n/
Try the demo, highlight some rows and then reload the page. Notice that this works on a paginated dataTable as well!
Update. When you are using a AJAX datasrc reloaded each 30 secs, I think you could skip the initComplete and just rely on the draw.dt event :
var table = $('#example').DataTable();
$('#example').on('draw.dt', function() {
if (!Array.isArray(selectedRows)) {
selectedRows = [];
} else {
selectedRows.forEach(function(index) {
$(table.row(index).node()).addClass('highlight');
})
}
})
Completely untested, but cannot see why it shouldnt work.
This should do the trick:
$('#id tbody > tr').eq(rowindex)
or
$('#id tbody > tr').eq(rowindex).children().addClass('myClass');
My goal is to highlight a row if two columns contain the same string within a row using datatables
I am not sure how would I compare two columns. I want to do something like this.
This is part of my code
"columnDefs":[
{
"targets":[3,4],
"render": function ( data, type, full, meta ) {
if value of 3 = 4 {
//highlight the row
}
}
} ],
Thanks in advance.
SOLUTION
Use rowCallback option to define a callback function that will be called when row would be drawn.
$('#example').dataTable({
"rowCallback": function(row, data, index){
if (data[3] === data[4]) {
$(row).addClass('selected');
}
}
});
DEMO
See this jsFiddle for code and demonstration.