I have datatable which is showing details rows. It is working fine for first time but when I click on second or third child row then it shows duplicated rows, I mean the rows which were in 1st child rows.
$(document).ready(function() {
var table = $('#example').DataTable( {
"ajax": {
"url":"{{ route('admin.requestReport') }}",
"dataType":"json",
"type":"POST",
"data":{"_token":"{{ csrf_token() }}"}
},
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "counter" },
{ "data": "start_date" }
],
/* "order": [[1, 'asc']], */
searching: false
} );
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
} );
} );
I did console.log() and found the problem, but i need to guideline to solve it. The problem I found which is here
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
I did console.log(row.data()) which is also passing the previous clicked rows into function.
I would like to request you kindly guide me how can I pass the data() of single row into function. I would like to appreciate. Thank you so much.
Related
I have a data table using jquery that display a list of data. I implemented a checkbox on the first column that I can check for each record or check all the records at once. If there is one checkbox or more selected then the approve and reject button would show up. While all these can work at the moment but if I select a next page and start checking any checkbox, the approve/reject button will not display.
Code:
<article class="col-xs-6 text-right">
<button id="approveButton" class="btn btn-success update-button" value="1">Approve</button>
<button id="rejectButton" class="btn btn-danger update-button" value="2">Reject</button>
</article>
var $table = $("#dt_basic").DataTable({
"scrollY": ($(window).height() - 270)+"px",
"scrollX": false,
"pageLength": ' . Yii::$app->params['settings']['listing_length'] . ',
"processing": true,
"serverSide": true,
"columnDefs": [{ "targets": [0, 6], "searchable": false, "orderable": false, "visible": true, className: "text-center-desktop" }],
"deferLoading": ' . $total . ',
"order": [],
"ajax": "' . Yii::$app->urlManager->createUrl(['xxxx']) . '",
"sDom": "<\'dt-toolbar\'<\'col-xs-12 col-sm-9\'f><\'col-sm-3 hidden-xs\'l>>r"+
"t"+
"<\'dt-toolbar-footer\'<\'col-sm-5 col-xs-12 hidden-xs\'i><\'col-xs-12 col-sm-7\'p>>",
"autoWidth" : true,
"preDrawCallback" : function() {
responsiveHelper_dt_basic = new ResponsiveDatatablesHelper($(\'#dt_basic\'), {tablet : 1024, phone : 480});
},
"rowCallback" : function(nRow) {
responsiveHelper_dt_basic.createExpandIcon(nRow);
},
"drawCallback" : function(oSettings) {
responsiveHelper_dt_basic.respond();
var pagination = $(this).closest(".dataTables_wrapper").find(".dataTables_paginate");
pagination.toggle(this.api().page.info().pages > 1);
}
});
$("#approveButton").hide();
$("#rejectButton").hide();
$("#masterCheck").on("click", function (e) {
if ($(this).is(":checked", true)) {
$(".subChk").prop("checked",true);
} else {
$(".subChk").prop("checked", false);
}
});
//This would not detect if checkbox is ticked in next page
$("input:checkbox").on("change",function(){
if ($("input:checkbox:checked").length > 0) {
$("#approveButton").show();
$("#rejectButton").show();
} else {
$("#approveButton").hide();
$("#rejectButton").hide();
}
});
$(".update-button").on("click", function(e) {
e.preventDefault();
var status = $(this).val();
let allVals = [];
$(".subChk:checked").each(function() {
allVals.push($(this).attr("id"));
});
console.log(allVals);
let join_selected_values = allVals.join(",");
$.ajax({
url: "updatewithdrawbulk",
type: "UPDATE",
data: {
ids: join_selected_values,
type: status
},
success: function(data) {
location.reload();
},
error: function (data) {
alert("There is some error, please try again");
}
});
});
After going to next page, checking the master checkbox will work (checked all sub checkbox as well) and approve/reject button will show. My only issue is when I tick any checkbox individually, it will not show the buttons.
I was wondering if this is an issue with the code or jquery data table?
The issue is that when you are attaching these .on bindings - it will only attach for the elements that currently exist in the html to be found.
When your next set of rows are drawn - these do not have the events bound to them.
If you hook into the event callback that tells you when new rows have appeared - you should bind your events again so that these new rows work as expected.
In the sample I would expect this to be achieved within the drawCallback event.
I am using Datatables plugin and dynmically populating the table with the data returned from server. on different table draws the returned data has variable no of columns. On each table intilization the code is checking if there has been previous initializations and removes it before creating a new table with dynamic data, using this code:
if ( $.fn.dataTable.isDataTable( '#contracts_forecast' ) ) {
$('#contracts_forecast').DataTable().clear();
$('#contracts_forecast').DataTable().destroy();
$('#contracts_forecast tbody').empty();
$('#contracts_forecast thead').empty();
}
On the serverside I am manually editing the data and updating the database. When the database is updated with new data , I want to refresh the table so the change is reflected in the table. In order to do that I am using an POST SUBMIT event, which is triggered after the data is submitted to server and then call the function getDT(filter_product_code, filter_product_name) to update the table with new data
PROBLEM:
When the post submit event is triggered , it recalls the function getDT(filter_product_code, filter_product_name); and change is reflected. BUT THE NEW TABLE with UPDATED IS ADDED TO CURRENT TABLE WITHOUT THE OLD TABLE BEING DESTROYED Which leaves me with two same tables on screen
p.s I am assuming every time getDT() function is called it should check for if table is initialized and destroy it before creating a new one using the same
$(document).ready(function() {
$('#filter').click(function(){
var filter_product_code = $('#filter_product_code').val();
var filter_product_name = $('#filter_product_name').val();
if(filter_product_code == '' || filter_product_name == '')
{
alert('Select Both filter option');
}
var columns = [];
getDT(filter_product_code, filter_product_name);
function getDT(filter_product_code, filter_product_name) {
$.ajax({
serverSide: true,
type:'POST',
url: "/XXX/_fetch.php",
data: {filter_product_code: JSON.stringify(filter_product_code),
filter_product_name: JSON.stringify(filter_product_name)},
success: function (data) {
data = JSON.parse(data);
columnNames = Object.keys(data.data[0]);
for (var i in columnNames) {
columns.push({data: columnNames[i],
title: capitalizeFirstLetter(columnNames[i])});
}
if ( $.fn.dataTable.isDataTable( '#contracts_forecast' ) ) {
$('#contracts_forecast').DataTable().clear();
$('#contracts_forecast').DataTable().destroy();
$('#contracts_forecast tbody').empty();
$('#contracts_forecast thead').empty();
}
table = $('#contracts_forecast').DataTable({
data: data.data,
columns: columns,
dom: "Bfrtip",
select: true,
buttons: [
{ extend: "create", editor: editor },
{ extend: "edit", editor: editor },
{ extend: "remove", editor: editor }
],
"columnDefs": [
{
"targets": [0],
"visible": false,
"searchable": false
},
{ className: "tablecolumns", targets: "_all" },
]
} );
$('#contracts_forecast').on( 'click', 'tbody td:not(:first-child)', function (e) {
editor.inline( this );
} );
}
});
editor.on( 'postSubmit', function ( e, json, data, action, xhr ) {
getDT(filter_product_code, filter_product_name);
});
}
});
} );
I was doing a mistake by declaring the column variable outside function. Each time the function was called it was adding to already existing columns. So just needed to define column variable inside function.
getDT(filter_product_code, filter_product_name);
function getDT(filter_product_code, filter_product_name) {
var columns = [];
$.ajax({
serverSide: true,
// paging: true,
// retrieve:true,
type:'POST',
How do I delete my selected rows from datatables that use a local array for data? This is how I initialised my table:
var selected = Array();
var dataSet = [];
var rowItem = "";
$(document).ready(function () {
var table = $("#table").DataTable({
"data": dataSet,
"filter":false,
"language": {
"search": "",
"searchPlaceholder": " Search"
},
"select": {
"style": 'multi'
},
"ordering": true,
"lengthChange": false,
"columns": [
{ "title": "Name"},
],
"responsive": true,
"processing":true,
}).columns.adjust()
.responsive.recalc();
new $.fn.dataTable.FixedHeader(table);
This is how I'm trying to delete the selected rows from my tables:
$("#roleSection").on("click","#removeRole",function (e) {
selected = table.rows('.selected').data().toArray();
console.log(selected);
$.each(selected, function (id, value) {
console.log(value);
dataSet.splice($.inArray(value, dataSet), 1);
table.row(selected).remove().draw();
});
console.log(dataSet);
return false;
});
For some reason the items that are not deleted are being deleted and the table does not get updated at all.
I think you can find your answer over here
Basically, you have to change your line selected = table.rows('.selected').data().toArray(); to table.rows( '.selected' ).remove().draw();
And remove the additional code.
You also don't have to worry about looping through the list because table.rows('.selected') gets all the rows with the class selected and then remove() deletes them all for you.
Edit: If the dataSet is not updated automatically, then I think this might answer your second query
$("#delete").on("click", function (e) {
let newDataSet = [];
table.rows( '.selected' ).remove().draw();
table.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
let row = this;
newDataSet.push(row.data());
});
dataSet = newDataSet;
});
I've use datatable jquery with child-row. Normal, I selected a main row, i use
$('#table tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
//do this
}
else {
table.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
//do this
}
});
When use this, i click any child-row, it effect together. Now, i want to don't click to child-row, how can i do it, using javascript or jquery ?
Look at the picture sample.
I changed the behavior and fixed some things that can be traced by to DataTables example.
play with this one and see if it is closer to what you want. It assumes a single select. If you pick a row in the child, the parent becomes selected.
http://live.datatables.net/fowiduzi/3/edit
$(document).ready(function () {
var table = $('#example').DataTable({
"data": testdata.data,
select: "single",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": '',
"render": function () {
// Use Font Awesome for the expander in the first cell
return '<i class="fa fa-plus-square" aria-hidden="true"></i>';
},
width: "15px"
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
// get the Font Awesome container
var tdi = tr.find("i.fa");
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tdi.first().removeClass('fa-minus-square');
tdi.first().addClass('fa-plus-square');
}
else {
// check to see if the child row exists.
// dont want to overwrite it if its already there.
if (row.child() && row.child().length > 0) {
row.child.show();
}
else {
// Open this row
row.child(format(row.data())).show();
}
tdi.first().removeClass('fa-plus-square');
tdi.first().addClass('fa-minus-square');
}
});
// Keeps the expander from being selected
table.on("user-select", function (e, dt, type, cell, originalEvent) {
if ($(cell.node()).hasClass("details-control")) {
e.preventDefault();
}
});
// If the parent row gets deselected by the user, deselect any
// selected child rows
table.on("deselect", function (e, dt, type, indexes) {
if (type === 'row') {
var child = dt.row(indexes[0]).child();
if (child && child.length > 0) {
$(child[0]).find(".selected").removeClass("selected");
}
}
});
$("#example").on("click", ".dt-childtable tr", function () {
var tr = $(this).closest("tr");
var childTbl = tr.closest("table");
var parentRow = childTbl.closest("tr").prev();
// see if this row is already selected
var isSelected = tr.hasClass("selected");
// remove previous selects from child table
childTbl.find(".selected").removeClass("selected");
if (isSelected) {
// this is a behavior question do you want the parent row to deselect with
// when the child row is.
//table.rows(parentRow).deselect();
} else {
tr.addClass("selected");
// if the child is selected, make sure the parent is selected but
// don't want to trigger a select event if the row
// is already so check if selected
if (!$(table.row(parentRow).node()).hasClass("selected")) {
table.rows(parentRow).select();
}
}
});
});
This code prevents the rows from being selected/unselected from occurring on the details-control click.
It also uses font-awesome from instead of the icons shown in the datatables example.
$(document).ready(function () {
// Normal table definition
var table = $('#example').DataTable({
"data": testdata.data,
select:"single",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": '',
"render": function () {
Instead of using the images provided from else where and adding it to my project
I use the Font Awesome as the expander
return '<i class="fa fa-plus-square" aria-hidden="true"></i>';
},
width:"15px"
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing details
// Note the click event is only on the cell with the details-control class
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var tdi = tr.find("i.fa");
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
// change the two font awesome icons
tdi.first().removeClass('fa-minus-square');
tdi.first().addClass('fa-plus-square');
}
else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
tdi.first().removeClass('fa-plus-square');
tdi.first().addClass('fa-minus-square')
}
});
// This event handler prevents the details-control from changing the select row from occurring
table.on("user-select", function (e, dt, type, cell, originalEvent) {
if ($(cell.node()).hasClass("details-control")) {
e.preventDefault();
}
})
});
I am using DataTables to create a list of selectable phone numbers, my function is as follow:
function search(areacode) {
areacode = typeof areacode !== 'undefined' ? areacode : 239;
$("#did_search").fadeIn();
var table = $('#example').DataTable( {
"bDestroy": true,
"ajax": "/Portal/manage/search_bulkvs/" + areacode,
"columns": [
{ "data": "did" },
{ "data": "city" },
{ "data": "state" },
{ "data": "action" },
],
"columnDefs": [
{ "visible": false, "targets": 3 }
]
} );
$('#example tbody').on( 'click', 'tr', function () {
var row_object = table.row( this ).data();
$("label[for = did_label]").text(row_object.action);
$('input[name="did"]').val(row_object.action);
} );
}
The end of the function $('#example tbody') -- allows me to select the data from the table that I need and set the value of my label/input for form processing. However, after I run this function a second time I am unable to select this data anymore.
My debugging has led to this error: Uncaught TypeError: Cannot read property 'action' of undefined
I thought that row_object would be defined every time that the function is run, but it looks like it isnt.
Does anyone have any suggestions as to how I can retrieve this data from the table after the function has been run more than once?
If the ajax call replaces the tbody element of the table, you will need to attach your delegated event handler to a non-changing ancestor (e.g. $('#example').on or even $('#example').parent().on(.
You also want to avoid repeatedly setting up handlers if search is called multiple times (or call off before on).
e.g.
$('#example tbody').off('click').on( 'click', 'tr', function () {
var row_object = table.row( this ).data();
$("label[for = did_label]").text(row_object.action);
$('input[name="did"]').val(row_object.action);
} );
Since you're using ajax, you need to bind your click object on each draw using DataTables.fnDrawCallback, like this:
function search(areacode) {
areacode = typeof areacode !== 'undefined' ? areacode : 239;
$("#did_search").fadeIn();
var table = $('#example').DataTable( {
"bDestroy": true,
"ajax": "/Portal/manage/search_bulkvs/" + areacode,
"columns": [
{ "data": "did" },
{ "data": "city" },
{ "data": "state" },
{ "data": "action" },
],
"columnDefs": [
{ "visible": false, "targets": 3 }
],
"fnDrawCallback": function(){
$("tbody tr td",$(this)).click(function(e){
.... Your click code here ....
});
}
} );
}
It is not that this becomes undefined. This error message
Uncaught TypeError: Cannot read property 'action' of undefined
usually means that you are calling a function from an undefined object (here is row_object), or the function you are calling (action) is not on the object.
Yes, the definition of variable row_object is fine. But I think you can console.log it to see whether it is assigned to some value correctly every time.