So I'm using jQuery child rows to display some data within a parent row. After displaying initially via Ajax, I do another ajax request and change data in the datatable. Now, if I try to expand it, it shows the rows. However, if I again try to change data in the datatable, it says d is not defined.
Here is my code when I initially load data in the datatable.
$.ajax({
url: "GetGridDetails?decodeID="+decoderFileSelected,
type: "GET",
dataType: 'json',
success: function (myData) {
if(myData != null){
console.log("my data is:"+myData);
var table = $('#dashNumTable').DataTable({
destroy: true,
data: myData ,
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "S" },
{ "data": "W" },
{ "data": "SA" },
{ "data": "DDS" },
{ "data": "AAS" },
{ "data": "ABS" },
{ "data": "BIN" },
{ "data": "ET" }
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing details
$('#dashNumTable tbody').on('click', 'td.details-control', function () {
//alert("clicked plus!");
var tr = $(this).closest('tr');
var row = table.row(tr);
//var row = $('#dashNumTable').DataTable().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');
}
});
}//if code ends..
else{
alert("There are no base numbers for the selected decoder ring file...");
}
} //end of success function...
});
This generates table with a plus button to expand and minus button to contract.
Code to refresh and add new data when an ajax event is fired.
$(document).on("click", "#showHGAPartBtn", function(){
// clear the eixisting table contents
//alert("show button clicked!");
var decoderFileSelected = $("#decoderFile").val();
//$('#dashNumTable').empty();
// var clearTable = $('#dashNumTable').DataTable();
// clearTable.clear().draw();
//clearTable.rows().remove();
$('#dashNumTable').DataTable().ajax.reload();
//get the fresh data..
$.ajax({
url: "GetGridDetails?decodeID="+decoderFileSelected,
type: "GET",
dataType: 'json',
success: function (data) {
//if(myData != null){
//console.log("my data is:"+myData);
var table = $('#dashNumTable').DataTable({
// destroy: true,
cache: false,
processing: true,
data: data ,
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "S" },
{ "data": "W" },
{ "data": "SA" },
{ "data": "DDS" },
{ "data": "AAS" },
{ "data": "ABS" },
{ "data": "BIN" },
{ "data": "ET" }
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing details
// $('#dashNumTable').on('click', 'tbody td.details-control', function () {
$('#dashNumTable').delegate('tbody td.details-control', 'click', function () {
//alert("clicked plus!");
var tr = $(this).closest('tr');
//table.ajax.reload();
var row = table.row(tr);
// alert("Row is :"+row);
//var row = $('#dashNumTable').DataTable().row(tr);
console.log(tr);
console.log(row);
console.log(row.child.isShown());
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');
}
});
// }//if code ends..
// else{
// alert("There are no base numbers for the selected decoder ring file...");
//}
},
//end of success function...
error: function(response){
console.log(response);
}
});// end of AJAX call
Here is the format function, which returns error in second time.
function format (d) {
//alert(d.stringify);
//alert(JSON.stringify(d));
var rowSelectedBaseNumbers = d.HGA_BASE_NUMBERS;
// `d` is the original data object for the row
//alert(rowSelectedBaseNumbers);
var selectedBaseNumbersDropdown = $("#selBaseNumbers").val();
var initial = "<table cellpadding='0' cellspacing='0' class='innerDataTbl'><tr class='shown'> <th>Dash No.</th> <th>Heads</th>";
var finalReturn = "";
var endHeaders = "</tr>";
var middleContentHeaders = "";
//iterate over the base numbers now
for(var i=0;i< selectedBaseNumbersDropdown.length; i++){
middleContentHeaders += "<th>"+selectedBaseNumbersDropdown[i]+"</th>";
}
var beginTRCheckboxes = "<tr><td>"+d.DIGIT+0+","+d.DIGIT+1+"</td><td>Up,Dn</td>";
var endTRCheckboxes = "</tr>";
var endTable = "</table>";
//iterate over the total base numbers again to create respective checkboxes
var checkboxes = "";
for(var i=0;i< selectedBaseNumbersDropdown.length; i++){
//is the selected base number already selected?
if($.inArray(selectedBaseNumbersDropdown[i], rowSelectedBaseNumbers) == -1){
//not found
//display checkbox as it is
checkboxes += "<td><input type='checkbox'/></td>";
}
else{
//found
//mark checkbox already selected
checkboxes += "<td><input type='checkbox' checked='checked' disabled/></td>"
}
}
//generate final return now
finalReturn = initial+middleContentHeaders+endHeaders+beginTRCheckboxes+checkboxes+endTRCheckboxes+endTable;
return finalReturn;
}
The error returned is
typeerror - d is not defined
make a failSafe scenario in your format function for whenever no data is available, the code will not execute.
function format (d) {
if (d) { return null; }
...
}
Are you sure that the code
row.data()
actually returns a value? => Try to figure that out.
Also, what is d? Try to make your code as easy as possible to read. We developers are writers. Not for the computer, but for our colleagues who sometimes need to read our code to understand what we are trying to accomplish.
Related
I'm currently working on a condominum program. The goal of this issue is when one Apartment row is clicked on the Parent table all the months - related to that apartment - must be displayed on the Child table.
The click/select/deselect is working fine but I can not obtain all the twelfth months.
This is my actual tables layout (example 1):
And this is my actual tables layout (example 2):
My code to childTable is:
var childTable = $('#child').DataTable( {
"pageLength": 12,
ajax: {
url: "ajax/query_pagquotas.php", // This is the URL to the server script for the child data
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var rows = data.data[i];
if (rows.ID === ID) {
return [rows];
}
}
} else {
return [];
}
}
},
columns: [
{ "data": "ID" },
{ "data": "DATA" },
{ "data": "MES" },
{ "data": "VALOR" },
{ "data": "METODO" },
{ "data": "ESTADO" },
{ "data": "OBS" }
]
} );
Thanks for your help Masters
[edited]
Ups! If condition at the end does not make the 'deselect' work...
This is my full code at the moment:
$(document).ready(function() {
var parentTable = $('#parent').DataTable( {
ajax: "ajax/dbfraccoes.php",
"language": {
"sSearchPlaceholder": "Apto ou Proprietário...",
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Portuguese.json",
},
"processing": true,
"scrollY": "200px",
"scrollCollapse": true,
"paging": false,
pageLength: 5,
select: {
style: 'single'
},
columns: [
{ "data": "ID","searchable": false },
{ "data": "APTO" },
{ "data": "FRACCAO"},
{ "data": "PROPRIETARIO" },
{ "data": "VALOR_QUOTA","searchable": false, className: "cssValores"},
{ "data": "OBS" }
]
} );
// tabela Child ------------------------------------------
var childTable = $('#child').DataTable( {
columnDefs: [{
targets: 6,
render: function(data, type, row, meta){
if(type === 'display' && data === 'EMITIDO'){
data = '<td style="text-align:center"><button type="button" class="btn btn-info btn-sm cssButton center" title="Emitido Aviso de Recibo a pagamento">EMITIDO</button></td>'+
'<div class="links">' +
'Editar ' +
'</div>';
}else if (type === 'display' && data === 'AGUARDA'){
data = '<td style="text-align:center"><button type="button" class="btn btn-warning btn-sm cssButton center" title="Limite de pagamento ultrapassado. Em período de tolerância.">AGUARDA</button></td>'+
'<div class="links">' +
'<a href="<?php echo WEB_URL;?>credit_debit/gest_quotas.php?spid='+
row['pqid']+'#insert">Editar</a> ' +
'</div>';
}
return data;
}
}],
"paging": false,
"searching": false,
"language": {
"zeroRecords": "<center>Clique na tabela acima, na linha do apartamento que pretende. <br/>Os dados da fracção/apartamento selecionado acima serão reflectidos nesta tabela</center>",
},
ajax: {
url: "ajax/query_pagquotas.php",
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
var rows = []; // create an empty array
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var row = data.data[i];
if (row.ID === ID) {
rows.push(row);
}
}
}
return rows;
},
},
columns: [
{ "data": "pqid" },
{ "data": "ID"},
{ "data": "DATA" },
{ "data": "MES"},
{ "data": "VALOR", className: "cssValores"},
{ "data": "METODO" },
{ "data": "ESTADO" },
{ "data": "OBS" }
]
} );
// This will load the child table with the corresponding data
parentTable.on( 'select', function () {
childTable.ajax.reload();
} );
//clear the child table
parentTable.on( 'deselect', function () {
childTable.ajax.reload();
} );
} );
The simplest way to adjust your existing code, is to change the logic in your dataSrc: function (data) {...}.
At the moment, you are only creating an array of one item.
So, instead you can do this:
dataSrc: function (data) {
var selected = parentTable.row( { selected: true } );
var rows = []; // create an empty array
if ( selected.any() ) {
var ID = selected.data().ID;
for (var i=0; i < data.data.length; i++) {
var row = data.data[i]; // change the variable name to "row"
if (row.ID === ID) {
rows.push(row); // add the new row to your array of rows
}
}
}
return rows; // return your array of rows
}
The most important line here is: rows.push(row); which is how JavaScript adds a new item to the end of an array.
So, now at the end of your dataSrc function you will either have an empty array [] if no rows were selected, or you will have an array of rows which match your ID.
That should solve your current problem.
The above approach should work - but it involves fetching every child row, every time - and then filtering out the ones you do not want to show.
You can probably improve on this by submitting the ID of the selected row as part of the child table's ajax URL. You can move the relevant code from its current location into your parentTable's on(select) function:
var selectedID = -1
parentTable.on( 'select', function () {
var selected = parentTable.row( { selected: true } );
if ( selected.any() ) {
selectedID = selected.data().ID;
}
childTable.ajax.reload();
} );
I do not know how you have implemented your ajax/query_pagquotas.php, so I am not sure of the best way to pass the selectedID parameter to it.
Normally I would append it as a query parameter in your ajax parameters:
data: 'id=' + selectedID
You may already know how to do this yourself.
Once you have passed the selectedID to your PHP, then you can use it to return only the records you want to display - and you can remove all of the existing dataSrc: function (data) {...} logic from your child table definition.
*
My Task is to get Nested DataTbless after making an ajax call.
I'm Getting the function working. Everytime I make a call it returns the data in main Datatable.
But, On Ajax call it gives me rowData is undefined error in Nested datatable.
Since I'm new at using Jquery I couldn't figure out the logical solution.
*
function ts_data(tabledata,tableChild,Expected_hrs,Hours_logged,Working_days,table_month){
$(document).ready(function() {
var table=$('#example').DataTable( {
"data": tabledata,
"retrieve": true,
"columns": [{
className: 'details-control',
orderable: false,
data: null,
defaultContent: ''
},
{ "data": "Fullname"},
{ "data": "Hours" },
{ "data": "Present_Hours_month"},
{ "data": "Working_Days" },
{ "data": "Month_Year"}],
"order": [[1, 'asc']]
} );
function format ( rowData ) {
console.log(rowData);
var file = jQuery.grep(tableChild, function(obj) {
return obj.Fullname === rowData.Fullname;});
var div = $('<table/>');
div.DataTable( {"paging": false,
"ordering": true,
"info": false,
"data": file,
"columns": [
{ "title": "Fullname", "data": "Fullname" },
{ "title": "Date","data": "Date" },
{ "title": "Day","data": "Day" },
{ "title": "Logged_Hours","data": "Logged_Hours" },
{ "title": "Present_Hours","data": "Present_Hours" }],
"order": [[1, 'asc']]})
return div;
}
// 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');
}
} );
});
};
function getMonth(){
$(document).ready(function() {
var month_yr = $('#recent').val();
$("#AjaxLoader").show();
$.getJSON('/attendance_log' + '/' + month_yr,
function(data) {
var tabledata = data.Main,
tableChild = data.Child,
Expected_hrs = data.Expected_hrs,
Hours_logged = data.Hours_logged,
Working_days = data.Working_days;
table_month = data.table_month;
console.log(tabledata);
/* Formatting function for row details - modify as you need */
document.getElementById("table_name").innerHTML = "Attendance log for " + table_month + " Month";
$("#AjaxLoader").hide();
ts_data(tabledata,tableChild,Expected_hrs,Hours_logged,Working_days,table_month);
});
})
}
var startDate = new Date();
$('.from').datepicker({
autoclose: true,
minViewMode: 1,
format: 'mm-yyyy'
}).on('changeDate', function(selected){
startDate = new Date(selected.date.valueOf());
startDate.setDate(startDate.getDate(new Date(selected.date.valueOf())));
$('.to').datepicker('setStartDate', startDate);
});
window.onload = function(){
var today = new Date().toISOString().substr(0, 10);
var month_yr = today.substring(5, 7) +"-" + today.substring(0,4);
document.getElementById("recent").setAttribute("value", month_yr);
getMonth()
};
On document.ready, my Datatable loads accordingly.
What I need to do is build a feature that reloads the Datatable if the user conducts a search.
So the Datatable loads like this:
$(document).ready(function()
{
$('#searchSubmit').on('click', function() // used for searching
{
var searchbooking = $('#searchbooking').val();
var searchquote = $('#searchquote').val();
var searchtli = $('#searchtli').val();
if(searchbooking == "" && searchquote == "" && searchtli == "")
{
$('.message').text('You did not enter any search criteria.');
return false; // making sure they enter something
}
else
{
$.post('api/searchAll.php', {searchbooking:searchbooking, searchquote:searchquote, searchtli:searchtli}, function(data)
{
// what do i do here???
// how do I get the return results to load
});
}
});
// if the user does not enter any search parameters, load everything
$('#example1').DataTable({
"ajax": {
"url": "api/displayQnams.php",
"type": "POST",
"dataSrc": ''
},
"columns": [
{ "data": "" },
{ "data": "column1" },
{ "data": "column2" },
{ "data": "column3" }
],
"iDisplayLength": 25,
"order": [[ 6, "desc" ]],
// and so on
});
});
As you will see in the above code, when the document is ready, if the user does not conduct a search, I load all of the data from the process called 'displayQnams.php'.
But if the user conducts a search, the parameters are sent to another process called 'qnamsSearch.php'.
How do I reload the datatable with the search results from 'qnamsSearch.php'?
I tried to create a variable from inside the post:
var dataUrl = data;
And I tried to call that variable in the ajax call:
"ajax": {
"url": dataUrl,
"type": "POST",
"dataSrc": ''
}
But the Datatable will not display anything and there are no console errors.
How can I make this work?
You can try using this.
After user click search button, below is the flow:
Clear datatables - datatables clear()
Add new data to the table - datatables rows.add()
Adjust column size (optional) - datatables adjust.columns()
Redraw back datatable with new data - datatables draw()
$(document).ready(function(){
var datatable = $('#example1').DataTable({
"ajax": {
"url": "api/displayQnams.php",
"type": "POST",
"dataSrc": ''
},
"columns": [
{ "data": "" },
{ "data": "column1" },
{ "data": "column2" },
{ "data": "column3" }
],
"iDisplayLength": 25,
"order": [[ 6, "desc" ]]
});
$('#searchSubmit').on('click', function(){
var searchbooking = $('#searchbooking').val();
var searchquote = $('#searchquote').val();
var searchtli = $('#searchtli').val();
if(searchbooking == "" && searchquote == "" && searchtli == ""){
$('.message').text('You did not enter any search criteria.');
return false; // making sure they enter something
} else {
$.post(
'api/searchAll.php',
{ searchbooking:searchbooking, searchquote:searchquote, searchtli:searchtli },
function(data) {
var newData = data;
datatable.clear().draw();
datatable.rows.add(newData); // Add new data
datatable.columns.adjust().draw(); // Redraw the DataTable
});
}
});
});
Sorry for the bad title. I am new to Rails and Javascript. I setup a DataTable using child rows following the DataTables documentation using a single ajax call to a JSON file.
I got that all working I now want to use my Rails controller to get the JSON from a Mongo DB. I also have that part working. What I am confused about is probably very simple and I am used to building a Rails table with active record BUT here I had a separate javascript called tests.js with my DataTable definition and the ajax call to a file. Can I now just pass in the JSON from the View somehow? I am not sure how to switch from the ajax call to using the JSON I now have from my controller
$(document).ready(function() {
var table = $('#queryone_table').DataTable( {
"ajax": "/objects.txt",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "transactionType" },
{ "data": "collationId" },
{ "data": "licensePlate" },
{ "data": "description" },
{ "data": "startDate" },
{ "data": "FeedComplete" },
{ "data": "RepoComplete" },
{ "data": "feedProcessingDuration" },
{ "data": "completeDuration" }
],
"order": [[1, 'asc']]
} );
Objects.txt I would now like to be a var from my View? With active record and MySQL I would build the table in the view looping over a dataset from controller but with the child row code already done in javascript I would like to leave that.
full javascript code
$(document).ready(function() {
var table = $('#queryone_table').DataTable( {
"ajax": "/objects.txt",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "transactionType" },
{ "data": "collationId" },
{ "data": "licensePlate" },
{ "data": "description" },
{ "data": "startDate" },
{ "data": "FeedComplete" },
{ "data": "RepoComplete" },
{ "data": "feedProcessingDuration" },
{ "data": "completeDuration" }
],
"order": [[1, 'asc']]
} );
// Add event listener for opening and closing details
$('#queryone_table 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');
}
} );
} );
function format ( d ) {
var foo = '<table id="queryinner_table" cellpadding="5" cellspacing="2" border="1" style="padding-left:50px;" class="table table-striped table-bordered table-hover table-condensed dataTable no-footer sub-table">';
// loop over table rows
var trow = "";
for (var i=0; i< d.nextrow.length; i++) {
var foo2 = '<tr>'+
'<td>Transaction Step:</td>'+
'<td>'+d.nextrow[i].transactionStep+'</td>'+
'<td>'+d.nextrow[i].elapsedSeconds+'</td>'+
'</tr>'
trow = trow + foo2
} //for loop
var foo2 = '</table>';
var res = foo.concat(trow);
res = res.concat(foo2);
return res;
}
This was poorly worded I have started a new project and will ask a few questions based on that code rather than rewrite this one.
I have a set of JSON data that are displayed using datatables. In one of the columns, I add a button and a text box only if the value in that column and another column meets a certain condition. this is the bit of code I used to do this:
$(document).ready(function (){
var alertTable = $('#alert-table').DataTable({
"jQueryUI": true,
"order": [ 3, 'desc' ],
"columns": [
{ "data": "source", "visible": false },
{ "data": "host" },
{ "data": "priority" },
{ "data": "ack", "render": function( data, type, row ) {
if (row.ack == "0" && row.priority > "2") {
return '<form><input class="ackname" type="text" value="Enter your name"><input class="ackbutton" type="button" value="Ack Alert" onclick="<get all items for that row and POST to a URL>"></form>';
}
return data;
}
},
],
"language": {
"emptyTable": "No Alerts Available in Table"
}
});
});
This works fine by adding a button and text in the cell. What I am looking to achieve is, when any of the button is been clicked, it should POST all the values for that row including what is typed in the text box to a URL which has another function that would extract those details and update the database and send back the refreshed data. I am new to datatables and jquery, any guide would be highly appreciated.
Have made some changes to the code, instead of form you can use div.
$(document).ready(function (){
var alertTable = $('#alert-table').DataTable({
"jQueryUI": true,
"order": [ 3, 'desc' ],
"columns": [
{ "data": "source", "visible": false },
{ "data": "host" },
{ "data": "priority" },
{ "data": "ack", "render": function( data, type, row ) {
if (row.ack == "0" && row.priority > "2") {
return '<div><input class="ackname" type="text" value="Enter your name"><input class="ackbutton" type="button" value="Ack Alert"></div>';
}
return data;
}
},
],
"language": {
"emptyTable": "No Alerts Available in Table"
}
});
$(document).on("click",".ackbutton",function() {
var currentIndex = $(this).parent().parent().index();
var rowData = alertTable.row( index ).data();
//extract the textbox value
var TextboxValue = $(this).siblings(".ackname").val();
var objToSave = {}; //Create the object as per the requirement
//Add the textbox value also to same object and send to server
objToSave["TextValue"] = TextboxValue;
$.ajax({
url: "url to another page"
data: JSON.stringify({dataForSave : objToSave}),
type: "POST",dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(datas) {
//Your success Code
},
error: function(error) {
alert(error.responseText);
}
});
});
});
Since both the pages are in same project, you can also do it using single ajax, passing all the values to server at once and then calling the other page internally from server and passing in the values using query string.
This is not a running code, rather to give you a basic idea on how to proceed.
Hope this helps :)