I am developing a web application for myself to learn JavaScript/jQuery, and I am trying to use dataTables plug-in for display data on page.
I am failing to implement Child Rows, to detail my data - I get "Uncaught ReferenceError" when tying to expand child row. I found on my searches, solutions for similar problems; but I'm having trouble applying to my code due the way I structured it for get data from a PHP file.
On solution I found, this problem was generated for using different variable names for the table on dataTables settings and click event.
In my case, my dataTables settings is inside a callback function, due to PHP request (It was the way I successfully did it work, after long hours trying - I was having problems with async on JavaScript), therefore I don't have it as a variable to make the reference.
The way I am getting data from PHP it's working, but I am not sure if it is the most appropriate manner.
I am looking for a solution to set the Child Rows without messing up my PHP request. This solution can be either by changing the way data is get from PHP or the way Child Rows is setted.
function dataJSON(callback) {
$.ajax({
url: "historicoTransacoes.php",
type: "GET",
dataType: "html",
}).done(function (data) {
callback(data);
}).fail(function () {
console.log("Erro na requisição");
});
};
function dataJSON2(data) {
d = JSON.parse(data);
console.log(d)
var table = $('#ultimosLancamentos').dataTable({
//"bProcessing": true,
//"serverSide": true,
data: d,
paging: true,
ordering: false,
info: true,
columns: [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{data: "local"},
{data: "tipotransacao"},
{data: "contain"},
{data: "contaout"},
{data: "valor"},
{data: "datatransacao"}
]
});
}
$('#ultimosLancamentos 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) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
'<tr>' +
'<td>' + d.descricao + '</td>' +
'</tr>' +
'</table>';
}
$(document).ready(function () {
dataJSON(dataJSON2);
var table = $('#ultimosLancamentos').dataTable;
});
Make it work with these changes:
function dataJSON() {
var d=[];
$.ajax({
url: "historicoTransacoes.php",
type: "GET",
dataType: "html",
async: false,
success : function(data) {
//console.log(data);
d.push(data);
}, error : function(req, err) {
console.log(err);
}
});
//console.log(d[0]);
return JSON.parse(d[0]);
};
function format(d) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
'<tr>' +
'<td>' + d.descricao + '</td>' +
'</tr>' +
'</table>';
}
d=dataJSON();
//console.log(d);
$(document).ready(function () {
var table = $('#ultimosLancamentos').DataTable({
//"bProcessing": true,
//"serverSide": true,
data: d,
paging: true,
ordering: false,
info: true,
columns: [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{data: "local"},
{data: "tipotransacao"},
{data: "contain"},
{data: "contaout"},
{data: "valor"},
{data: "datatransacao"}
]
});
$('#ultimosLancamentos 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');
}
});
});
The key was setting ajax async propertie to 'false', so I could pass the Json from request to a JavaScript variable.
Still don't know if it is the most apporpriete way, but it worked.
Any tips for improve this code are still welcome!
Related
Could you please assist me with this issue related to Bootstrap - Jquery Table?
I would like to retrieve data from a database server In JSON Format (through an ajax call) into a bootstrap DataTable and then reload the DataTable only.
Here you are the code, this will be run once pressed the click button (search):
var prova = null;
$(document).ready(function(){
prova = $('#prova_table').DataTable({
paging: true,
searching: false
});
prendivalori();
});
function prendivalori() {
$("#bottone").click(function() {
$("#prova_table").empty();
var sopravvissuti = $('#sopravvissuti').val();
var vita = $('#vita').val();
var provincia = $('#provincia').val();
var campi = $('#campi').val();
var table = $('#prova_table');
$.ajax({
type: 'GET',
url: './php/select.php',
data: {'sopravvissuti': sopravvissuti, 'vita': vita, 'provincia':provincia, 'campi':campi},
dataType: 'json',
success: function(data) {
table.append("<thead><tr><th class='th-sm'>Cognome</th><th class='th-sm'>Nome</th><th class='th-sm'>Sesso</th></tr></thead>");
console.log(data);
len=data[0].length;
table.append("<tbody>");
for(i=0; i< len; i++){
temp=data[0][i]
table.append("<tr><td>" + temp[1] + "</td><td>" + temp[0] + "</td><td>"
+ temp[2] +"</td></tr>");
}
table.append("</tbody>");
$('#prova_table').DataTable().ajax.reload();
}
,
error: function(data) {
alert('Assicurarsi di aver selezionato tutte le caselle');
}
});
});
};
Here you are the error message received once clicked button data...
DataTables warning: table id=prova_table - Invalid JSON response. For more information about this error, please see http://datatables.net/tn/1
The json data received from the server are correct because we can see them properly into the table but we are unable to use all the functions Bootstrap DataTable provides like Pagination search and number of entries....
I'm using all the updated links for running the website ..
ETC ECT
Here you are a JSON response:
Many thanks in advance for all you kind support
Have a nice day
Andrea
You should not do table.append() and any other direct dom changes on table.
Jquery data table will do this for you if you pass options to it in right way.
Do it this way.
First initialize the datatable like below with column names if available
var table = $("#myTable").DataTable({
data:[],
columns: [
{ "data": "Cognome" },
{ "data": "Nome" },
{ "data": "Sesso" },
{ "data": "data di nascita" }
],
});
in on click of button, do a get ajax call and in done callback clear the table table.clear().draw(); and table.rows.add(result).draw() to render data to the table.
$.ajax({
url: "https://www.mocky.io/v2/5e89289e3100005600d39c17",
type: "get",
}).done(function (result) {
table.clear().draw();
table.rows.add(result).draw();
})
JSFiddle : https://jsfiddle.net/k0d1mzgL/
var table = $("#myTable").DataTable({
data:[],
columns: [
{ "data": "Cognome" ,"title": "Cognome"},
{ "data": "Nome" ,"title": "Nome"},
{ "data": "Sesso" ,"title": "Sesso"},
{ "data": "data di nascita","title": "data di nascita" }
],
});
$("#getDataBtn").click(function(){
$.ajax({
url: "https://www.mocky.io/v2/5e89289e3100005600d39c17",
type: "get",
}).done(function (result) {
table.clear().draw();
table.rows.add(result).draw();
}).fail(function (jqXHR, textStatus, errorThrown) {
//if failed
console.log("Due to https issue,this request cant be made, go check jsfiddle link provided in answer");
});
});
<link href="//cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" rel="stylesheet" >
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<table id="myTable">
</table>
<button id="getDataBtn">Get data</button>
When using the filter box of a datatable, the rowId remains on the first record, and I cannot figure out why.
Here is the datatable (simplified as much as possible):
$.ajax({
url: 'process/getData.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR){
var jsonObject = JSON.parse(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{
"data": "MONDAY",
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol)
{
$(nTd).html("<span class='checkMon'>+oData.MONDAY+</span>");
},
// columns for each work day
}
],
"paging": false,
"scrollY": 730,
"scrollX": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
},
error: function(jqHHR, textStatus, errorThrown) {
console.log('fail: '+ errorThrown);
return false;
}
});
Outside of the datatable, I have onclick event handler:
$('#example1').on('click', 'tr > td > .checkMon', function(e)
{
e.preventDefault();
var $dataTable = $('#example1').DataTable();
var tr = $(this).closest('tr');
var data = $dataTable.rows().data();
var rowData = data[tr.index()];
console.log(rowData.UID);
});
Prior to filtering, when I click any cell, the console reads the correct rowData.UID.
The problem is when I filter and click the cell again, the console reads the first row's rowData.UID.
Does anyone see why this is happening and how to fix it?
If what you want to achieve is simply log into the console UID property of the object that sourced the row that holds the <span> you've clicked, following approach should work:
$('#example1').on('click', '.checkMon', function(e)
{
e.preventDefault();
const dataTable = $('#example1').DataTable();
const rowData = dataTable.row($(this).closest('tr')).data();
console.log(rowData.UID);
});
Also, consider using ajax option. With that you won't need to waste performance destroying/re-creating your table and that will make your code cleaner and safer.
I have a table using Datatable plugin. I have filtered what I want to delete and after deletion, I manage to empty the value.
After that, if I want to filter using the same text again, for example, I have ba 1 and ba 2 and after deleting ba 1, it still shows the cell when I entered ba on the filter textarea field. It suppose to display the remaining ba which are not deleted yet.
For your information, I'm not using built in Datatable Ajax method.
what I'm trying to do is I want it to reload the table with the new data without refreshing the page after ajax on success. How to do that?
My datatable :
var table1 = $('#table1').DataTable(
{
pageLength : 500,
lengthChange: false,
deferRender: true,
scrollY: 800,
scrollCollapse: true,
scrollX: true,
bSort: false,
cache: true,
autoWidth: false,
columnDefs: [
{
targets: 0,
checkboxes:
{
selectRow: true
}
}
],
select: {
style: 'multi',
selector: 'td:not(:nth-child(4), :nth-child(5), :nth-child(6), :nth-child(9), :nth-child(10), :nth-child(13), :nth-child(14), :nth-child(15), :nth-child(16), :nth-child(17), :nth-child(18), :nth-child(19), :nth-child(20), :nth-child(21), :nth-child(22), :nth-child(23), :nth-child(24), :nth-child(25))'
}
});
Here's my filtering function code :
table1.columns().every(function ()
{
var table = this;
$('.filter', this.header()).on('keyup change', delay(function (settings, data, dataIndex)
{
if (table.search() !== this.value)
{
table.search(this.value).draw();
}
}, 500));
});
Here's my AJAX success code for deletion based on selected checkbox:
$('.btnN2').click(function(){
var answer = confirm('Delete N2 : Are you sure you want to delete selected items?');
if (answer)
{
console.log('yes');
var rows = $(table1.rows({selected: true}).$('input[type="checkbox"]').map(function()
{
return $(this).prop("checked") ? $(this).closest('tr').attr('data-getstockcode') : null;
}));
var getstockcodes = [];
$.each(rows, function(index, rowId)
{
console.log(rowId)
getstockcodes.push(rowId);
});
$.ajax({
url: 'del_n2',
type: 'GET',
data: {"getstockcodes": JSON.stringify(getstockcodes)},
dataType: 'JSON',
success:function(data){
console.log(data);
$(table1.rows({selected: true}).$('input[type="checkbox"]').map(function()
{
if($(this).prop("checked"))
{
$(this).parents("tr:eq(0)").find(".note2").val('');
console.log('reset');
}
}));
}
});
}
else
{
console.log('cancel');
}
});
Here's my insert data based on keyup event
$(".note2").keyup(delay(function()
{
var stockcode = $(this).data("stockcode");
var stockname = $(this).data("stockname");
var value = $(this).val().replace(/(\r\n|\n)/g, "\\n");
$.ajax({
url: 'saveNote2',
type: 'GET',
data: 'stockcode='+stockcode+'&stockname='+stockname+'&value='+value,
dataType: 'JSON',
success: function(data){
console.log(data);
},
error: function(data){
console.log(data);
}
});
}, 300));
Just add this in your success function
table1.ajax.reload()
If you are using ajax datatable or local you need to make it like this
table1.clear();
table1.rows.add(your response data array);
table1.draw()
I have a modal with a search box within it, which when the search button is hit, has an ajax call which goes to the controller, which then returns a table of results, which is then put into a div. Like so:
$.ajax({
url: url,
data: JSON.stringify(viewModel),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
cache: false,
type: "POST",
success: function (result) {
if (result.success === true) {
$("#searchResultsPlaceHolder").show();
$("#searchResultsPlaceHolder").html(result.view, function() {
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
});
}
},
error: function (responseText, textStatus, errorThrown) {
alert('Error - ' + errorThrown);
}
});
All that is fine, and works perfectly up until I try to make it a datatable. If I take out the lines
$("#searchResultsPlaceHolder").html(result.view, function() {
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
});
and just have
$("#searchResultsPlaceHolder").html(result.view)
it works fine, it gives me a table with my results. But as this is in a modal, and the returned results may get quite lengthy, I want to use a datatable to implement pagination and sorting. But whenever I apply the loadSearchDatatable function to the table after the div is populated with the returned html, I get the error:
table id=searchResultsTable - Ajax error
The datatable actually appears, with the sort buttons and paging buttons present, but none of them do anything, and the table is longer than the length I specified (5). Here is my datatable function:
function loadSearchDatatable() {
$('#searchResultsTable').dataTable({
ajax: "data.json",
"bLengthChange": false,
'iDisplayLength': 5,
"bSort": true,
"sPaginationType": "full_numbers",
"bFilter": false,
"sDom": 'ft<"bottom"ilp>',
"bDestroy": false,
"aaSorting": [[0, "asc"]]
});
};
Does anyone have any idea how to fix this error?
Use the code below instead:
$("#searchResultsPlaceHolder").html(result.view);
var noOfRows = $('#searchResultsTable tr').length;
if (noOfRows > 1) {
loadSearchDatatable();
}
Also remove ajax: "data.json", in your function loadSearchDatatable().
this is related to my previous question about jqgrid. im doing now a search button that would search my inputed text from the server and display those data (if there is) in the jqgrid. Now, what i did is i create a global variable that stores the filters. Here's my javascript code for my searching and displaying:
filter = ''; //this is my global variable for storing filters
$('#btnsearchCode').click(function(){
var row_data = '';
var par = {
"SessionID": $.cookie("ID"),
"dataType": "data",
"filters":[{
"name":"code",
"comparison":"starts_with",
"value":$('#searchCode').val(),
}],
"recordLimit":50,
"recordOffset":0,
"rowDataAsObjects":false,
"queryRowCount":true,
"sort_descending_fields":"main_account_group_desc"
}
filter="[{'name':'main_account_group_code','comparison':'starts_with','value':$('#searchCode').val()}]";
$('#list1').setGridParam({
url:'json.php?path=' + encodeURI('data/view') + '&json=' + encodeURI(JSON.stringify(par)),
datatype: Settings.ajaxDataType,
});
$('#list1').trigger('reloadGrid');
$.ajax({
type: 'GET',
url: 'json.php?' + $.param({path:'data/view',json:JSON.stringify(par)}),
dataType: Settings.ajaxDataType,
success: function(data) {
if ('error' in data){
showMessage('ERROR: ' + data["error"]["msg"]);
}
else{
if ( (JSON.stringify(data.result.main.row)) <= 0){
alert('code not found');
}
else{
var root=[];
$.each(data['result']['main']['rowdata'], function(rowIndex, rowDataValue) {
var row = {};
$.each(rowDataValue, function(columnIndex, rowArrayValue) {
var fldName = data['result']['main']['metadata']['fields'][columnIndex].name;
row[fldName] = rowArrayValue;
});
root[rowIndex] = row;
row_data += JSON.stringify(root[rowIndex]) + '\r\n';
});
}
alert(row_data); //this alerts all the data that starts with the inputed text...
}
}
});
}
i observed that the code always enter this (i am planning this code to use with my other tables) so i put the filter here:
$.extend(jQuery.jgrid.defaults, {
datatype: 'json',
serializeGridData: function(postData) {
var jsonParams = {
'SessionID': $.cookie("ID"),
'dataType': 'data',
'filters': filter,
'recordLimit': postData.rows,
'recordOffset': postData.rows * (postData.page - 1),
'rowDataAsObjects': false,
'queryRowCount': true,
'sort_fields': postData.sidx
};
return 'json=' + JSON.stringify(jsonParams);
},
loadError: function(xhr, msg, e) {
showMessage('HTTP error: ' + JSON.stringify(msg) + '.');
},
});
now, my question is, why is it that that it displayed an error message "Server Error: Parameter 'dataType' is not specified"? I already declared dataType in my code like above but it seems that its not reading it. Is there anybody here who can help me in this on how to show the searched data on the grid?(a function is a good help)
I modified your code based on the information from both of your questions. As the result the code will be about the following:
var myGrid = $("#list1");
myGrid.jqGrid({
datatype: 'local',
url: 'json.php',
postData: {
path: 'data/view'
},
jsonReader: {
root: function(obj) {
var root = [], fields;
if (obj.hasOwnProperty('error')) {
alert(obj.error['class'] + ' error: ' + obj.error.msg);
} else {
fields = obj.result.main.metadata.fields;
$.each(obj.result.main.rowdata, function(rowIndex, rowDataValue) {
var row = {};
$.each(rowDataValue, function(columnIndex, rowArrayValue) {
row[fields[columnIndex].name] = rowArrayValue;
});
root.push(row);
});
}
return root;
},
page: "result.main.page",
total: "result.main.pageCount",
records: "result.main.rows",
repeatitems: false,
id: "0"
},
serializeGridData: function(postData) {
var filter = JSON.stringify([
{
name:'main_account_group_code',
comparison:'starts_with',
value:$('#searchCode').val()
}
]);
var jsonParams = {
SessionID: $.cookie("ID"),
dataType: 'data',
filters: filter,
recordLimit: postData.rows,
recordOffset: postData.rows * (postData.page - 1),
rowDataAsObjects: false,
queryRowCount: true,
sort_descending_fields:'main_account_group_desc',
sort_fields: postData.sidx
};
return $.extend({},postData,{json:JSON.stringify(jsonParams)});
},
loadError: function(xhr, msg, e) {
alert('HTTP error: ' + JSON.stringify(msg) + '.');
},
colNames:['Code', 'Description','Type'],
colModel:[
{name:'code'},
{name:'desc'},
{name:'type'}
],
rowNum:10,
viewrecords: true,
rowList:[10,50,100],
pager: '#tblDataPager1',
sortname: 'desc',
sortorder: 'desc',
loadonce:false,
height: 250,
caption: "Main Account"
});
$("#btnsearchCode").click(function() {
myGrid.setGridParam({datatype:'json',page:1}).trigger("reloadGrid");
});
You can see the code live here.
The code uses datatype:'local' at the beginning (at the 4th line), so you will have no requests to the server if the "Search" button is clicked. The serializeGridData the data from the postData parameter of serializeGridData will be combined with the postData parameter of jqGrid (the parameter "&path="+encodeURIComponent('data/view') will be appended). Additionally all standard jqGrid parameters will continue to be sent, and the new json parameter with your custom information will additionally be sent.
By the way, if you want rename some standard parameters used in the URL like the usage of recordLimit instead of rows you can use prmNames parameter in the form.
prmNames: { rows: "recordLimit" }