"No data available in table" in DataTables - datatables

I get the message when trying to populate my table. Here's the simplified code.
$("#showUsers").on("click", function() {
$.ajax({
url: "/showUsers",
contentType: "application/json",
processData: false,
complete: function(data) {
$("#output").html(data.responseText);
$("#example").dataTable({
"aaData": data,
"aoColumns": [{
"sTitle": "Name",
"mDataProp": "name",
"sDefaultContent": ""
}, {
"sTitle": "Movie",
"mDataProp": "movie",
"sDefaultContent": ""
}]
});
}
});
});
And
<table id="example">
<thead>
<th>name</th>
<th>movie</th>
</thead>
</table>
The data is assigned valid json:
[{
"name": "Dan",
"movie": "Amelie"
}, {
"name": "Rob",
"movie": "Dungeon"
}]
I've read that sometimes it messes with the table itself and the headers and stuff so I tried removing the <thead> from my table definition but it results with the same issue.
Funny thing is that, if I replace "aaData":data with "aaData": plus the json itself, it works. But I can't make data fill the requirements needed by DT.
The ajax data comes from a node-mysql module which is working properly.
If I change data to data.responseText (this is the json as shown before) I get the warning requested unknown parameter 'name' from the data source for row 0.
I know this should be fairly simple for any not-so experienced DataTables user so thanks in advance. Somehow I'm being unable to sort it out.
SOLVED
The MySQL response comes with a data.responseJSON which is a working format to give to aaData. Thanks.

For the sake of flagging the question as awnsered.
SOLVED.
The mysql response comes with a data.responseJSON which is a working format to give to aaData. Thanks.

Just got wondering why my dataTable was not filling.
In addition to the correct json format needed with aaData, iTotalRecords and iTotalDisplayRecord, aaData needs to be an array (['a', 'b', ...]) and not an object ({'a': 'b', ...}).

Related

Datatables script DOM

I'm using datatables and I have created this javascript code
table = $('#examples').DataTable({
"ajax": {
type: "POST",
url: "./../../" + "/back-end/switch-ajax-listening/switch-ajax-listening.php",
dataType: "json",
data:
{
actionId: "page1GetAll"
}
},
dom : "B<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'<'#colvis'>p>>",
"buttons": [
{
extend: 'colvis',
postfixButtons: [ 'colvisRestore' ],
container : '#colvis',
columns: '0,1,2,3,4,5'
}
],
responsive: true,
"columns": [
{ "data": "idSelectPacketName"},
{ "data": "idSelectCompany" },
{"data":null,"defaultContent":"<button>View</button>"}
],
});
It works very well but I cannot be able to understand this part:
"B<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'<'#colvis'>p>>"
I have not written this string I have copied from an example but I am not able to understand how it works. Or have you known a guide to understand very well this string?
Because my problem is that some times the button is not aligned with the table, have you some ideas in order to solve it? Thanks.
It's a bit flakey as the author admits himself, for now, you need to put the Datatables keyletters in the correct places amongst the html tags. Something like:
dom : "<'row'<'col-sm-6'lB><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'<'#colvis'>p>>",
(placing the 'B' after the 'l')
You may also have to use CSS to obtain the desired layout.

JqWidgets treegrid issues wiring up dataAdapter object

I'm in the AngularJS environment, and trying to get a jqWidgets TreeGrid working.
I have the dataAdapter all wired up with the Json formatted data, however the grid renders only one row.
I also have a test treeGrid on the same page, and with sample data, which is working fine.
I'm putting the final Json data setting side-by-side to try and determine where I'm going wrong.
I've used this page as a guide to wire up the treegrid settings, etc. http://www.jqwidgets.com/jquery-widgets-documentation/documentation/angularjs/angularjs.htm
Here is the html showing the jqx treegrid directive for the "bad" grid:
<jqx-tree-grid jqx-instance="jqGridHierObj" jqx-settings="vm.jqGridHierSettings"></jqx-tree-grid>
And the "bad" Json data tree settings binded vm.jqGridHierSettings (too large to post inline):
http://www.bobmazzo.com/grid/TreeGrid_Data_Bad.txt
and here is the "good" grid with Employee test data :
HTML:
<jqx-tree-grid jqx-instance="jqGridEmpObj" jqx-settings="vm.jqGridEmpSettings"></jqx-grid>
vm.jqGridEmpSettings Json data :
http://www.bobmazzo.com/grid/TreeGrid_Data_Good.txt
and from my Angular controller code, a snippet of the javascript with Json data bindings :
I need help to figure out why the "bad" grid is not working ! And why it only renders one row, where is should be showing a hierarchy of data.
thanks.
Bob
I found the solution. You must define the “children” as an array type in the 'source' object; that is, prior to passing that object into the dataAdapter. See the dataFields property below :
var source = {
dataType: "json",
dataFields: [
{
"name": "id",
"type": "number"
},
{
"name": "field0",
"type": "string"
},
{
"name": "field1",
"type": "number"
},
{
"name": "field2",
"type": "number"
},
{
name: 'children', // MUST DEFINE CHILDREN AS ARRAY TYPE
type: 'array'
},
],
hierarchy: {
root: 'children'
},
id: 'id',
localData: myData
};
var dataAdapter = new $.jqx.dataAdapter(source);

jQuery DataTables - understanding how data is fed in, mRender/mData..?

I am struggling with grasping jQuery datatables (v1.10.1 via CDN), and the conventions used in the current version. Various documentation is confusing/lacking in 'complete' examples at best, conflicting at worst.
Please explain the current (v1.10.1) best practices with regards to defining the contents of a field.
I see lots of information about columns/mData/mRender/mDataProp, amongst others and I feel overloaded as to what each one means and/or when each should be used (see the 'research' section below for examples).
Secondly, where do I stand with regards to using dates and "set"/"display"/"filter"/"sort" (assuming that this is the route to take, with mData/mRender)?
Example
EDIT: Here's an example of some data in a fiddle:
var massData = [
{ "Column1": "test1", "Timestamp": "Sun Jul 27 2014 14:42:20 GMT+0100 (GMT Standard Time)", "Date": "18/10/2012" },
{ "Column1": "test2", "Timestamp": "Mon Jul 28 2014 14:42:20 GMT+0100 (GMT Standard Time)", "Date": "18/10/2016" },
{ "Column1": "test3", "Timestamp": "Wed Jul 22 2014 14:42:20 GMT+0100 (GMT Standard Time)", "Date": "18/01/2012" }
];
var keys = ["Column1", "Timestamp", "Date"];
var columns = [];
for (var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
columns.push({
"title": keys[keyIndex],
"data": keys[keyIndex],
"defaultContent": ""
});
}
$('#demo').html('<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"></table>');
$('#example').dataTable({
"data": massData,
"deferRender": true,
"scrollY": 400,
"scrollX": true,
"columns": columns
});
http://jsfiddle.net/2M97f/
Research
I see this question which has code using mRender, though my understanding is that filtering/sorting will use the actual data
I see this example and this documentation which uses aoColumnDefs, aTargets and mData..?
This question has a reply to "Filtering using the rendered text", but uses aoColumnDefs, mDataProp, and a 'renderDate()' function, but does NOT make use of mRender
The documentation for mRender and mData suggests that mRender depends upon mData..
Other documentation suggests fnRender/bUseRendered is deprecated
First of all, you're looking at examples from previous version (which are obvious based on the Hungarian Notation) So any example with mData may work now, but could be rendered unusable once legacy support is removed. While they can give you an idea of a direction to go, it's dangerous to find methods in the old API and then expect them to work as-is with 1.10. There is a version converter document that helps a lot to understand equivalents between old and new.
My preference is to use this example that uses the "columns" definition to specify the data field easily. You can also quickly and easily define things for each column there, such as searchable, title, visible, etc. See the API for others.
So, a sample Datatable in my code would look like this:
$('#example').DataTable( {
data: data,
columns: [
{ data: 'keyoffield1', title:'name title', visible:'false' },
{ data: 'keyoffield2', title:'position title' },
{ data: 'keyoffield3', title:'salary title here' },
{ data: 'keyoffield4', title:'office title here' }
]
} );
As for sorting, it's setup to recognize date fields out of the box for you, as you can see in your example (click on the header to change the sort) However, if you want to set default sorts such as asc, desc, etc, that's pretty easily done with columns.sort as you'll see in the API. There is a simple plugin to enhance sorting on fields that may not be formatted in a way that DataTables is built to use.
fnRender is gone, the closest equivalents are explained here. If you ignore those examples and the complaining that happened when it was removed, it's pretty easy to see how Allan was proceeding with the new methods like column.render for example.

Meteor with DataTables: Meteor._atFlush TypeError

I'm trying to use DataTables (via mrt add datatables) with Meteor. I've variously tried adding the $('#mytableid').dataTable() to the Meteor.subscribe callback, Meteor.autorun, Meteor.startup, and Template.mytemplate.rendered -- all resulting in the following exception and a No data available in table message.
Any pointers?
Exception from Meteor._atFlush: TypeError: Cannot call method 'insertBefore' of null
at http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:405:27
at LiveRange.operate (http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:459:11)
at LiveRange.replaceContents (http://localhost:3000/packages/liverange/liverange.js?bc1d62454d1fefbec95201344b27a7a5a7356293:403:17)
at http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:996:37
at withEventGuard (http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:105:16)
at http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:981:9
at http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:106:13
at http://localhost:3000/packages/deps/deps.js?1df0a05d3ec8fd21f591cfc485e7b03d2e2b6a01:71:15
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:3000/packages/underscore/underscore.js?47479149fe12fc56685a9de90c5a9903390cb451:79:11)
Update: Potentially related to this issue, for which the best solution found was to call dataTable() for each row -- not ideal in that case, and potentially catastrophic in mine given the very large number of rows.
Dror's answer is the right start for sure. Here's the best practice the way I see it currently:
HTML
<template name="data_table">
{{#constant}}
<table class="table table-striped" id="tblData">
</table>
{{/constant}}
</template>
JS:
Template.data_table.created = function() {
var _watch = Collection.find({});
var handle = _watch.observe({
addedAt: function (doc, atIndex, beforeId) {
$('#tblData').is(":visible") && $('#tblData').dataTable().fnAddData(doc);
}
, changedAt: function(newDoc, oldDoc, atIndex) {
$('#tblData').is(":visible") && $('#tblData').dataTable().fnUpdate(newDoc, atIndex);
}
, removedAt: function(oldDoc, atIndex) {
$('#tblData').is(":visible") && $('#tblData').dataTable().fnRemove(atIndex);
}
});
};
Template.data_table.rendered = function () {
if (!($("#tblData").hasClass("dataTable"))) {
$('#tblStudents').dataTable({
"aaSorting": []
, "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
, "sPaginationType": "bootstrap"
, "oLanguage": {
"sLengthMenu": "_MENU_ records per page"
}
, "aoColumns": [
{ "sTitle": "First Data", "mData": function (data) { return data.firstData },
]
});
$('#tblData').dataTable().fnClearTable();
$('#tblData').dataTable().fnAddData(Collection.find().fetch());
}
};
Since Meteor is reactive, you need to create an empty table first and then add the rows.
Create the table:
$('#myTable').dataTable( {
"aoColumns": cols, //the column titles
"sDom": gridDom
} );
Add rows should look something like:
var myCursor = myCollection.find({});
var handle = myCursor.observe({
added: function (row) {
//Add in here the data to the table
},
});
The answered approach still stands but requires some changes after two years.
There is no such thing as constant anymore.
Instead of an empty table, put the thead but NOT the tbody. This way, columns are defined properly.
Put the observer in the onRendered (not rendered anymore) and NOT on onCreated (not created anymore). Otherwise, table is only filled at first creation and not when you come back.
clear and fill methods on the onRendered are not required.
In the observe method, make sure that you are adding an array and not an object. Otherwise fnAdd cannot render content
fnRemove is no more. Use fnDeleteRow instead
I'm not sure if the "is visible check" is required or not. There does not seem to be a problem when you remove it too, so I removed it.
With the above remarks, here is the code:
Template.creamDealsList.onRendered(function () {
if (!($("#tblData").hasClass("dataTable"))) {
$('#tblStudents').dataTable({
// Those configuration are not really important, use it as they are convenient to you
"aaSorting": []
, "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
, "sPaginationType": "bootstrap"
, "oLanguage": {
"sLengthMenu": "_MENU_ records per page"
}
, "aoColumns": [
{ "sTitle": "First Data", "mData": function (data) { return data.firstData },
]
});
}
var _watch = Collection.find({});
var convertDocToArray = function (doc) {return [doc._id, doc.name]}
var handle = _watch.observe({
addedAt: function (doc, atIndex, beforeId) {
$('#tblData').dataTable().fnAddData(convertDocToArray(doc));
}
, changedAt: function(newDoc, oldDoc, atIndex) {
$('#tblData').dataTable().fnUpdate(convertDocToArray(newDoc), atIndex);
}
, removedAt: function(oldDoc, atIndex) {
$('#tblData').dataTable().fnDeleteRow(atIndex);
}
});
})
And simple HTML would be like:
<template name="data_table">
<table class="table table-striped" id="tblData">
<thead>
<th>Id</th>
<th>Name</th>
</thead>
</table>
</template>
This worked at least for me. I'm not seeing flush errors anymore. And also, when you render later, sometimes, there was a no data available message in the datatable and that disappeared as well.
Here's my implementation of dataTables in Meteor, using CoffeeScript and HTML. It works, and it's simpler, but may be less efficient than the existing answers for large tables (it's quick in my case though).
Template Function
Template.dashboard.rendered = ->
# Tear down and rebuild datatable
$('table:first').dataTable
"sPaginationType": "full_numbers"
"bDestroy": true
HTML
<template name="dashboard">
<table class="table table-bordered" id="datatable_3" style="min-width:1020px">
<thead>
<!-- code removed to save space -->
</thead>
<tbody id="previous-jobs-list">
{{#each jobs}}
{{> jobRow}}
{{/each}}
</tbody>
</table>
</template>
<template name="jobRow">
<tr>
<td>{{number}}</td>
<td>{{normalTime date}}</td>
<!-- more code removed to save space -->
</tr>
</template>
Where dashboard.jobs is a simple .find(...) on the collection.

How to populate a Extjs4 grid

I'm new to ExtJS4, I have been reading the doc and a book but can't have everything to work how I would like.
I have a form that is submited via AJAX, a JSON response is returned which migh contain none, one or more records. I want to show these records in a new window with a grid component, so the user can select just one record.
I can't make the JSON response to be populated into the grid, for starters,
Where is the JSON response stored?? I have the corresponding success and failure functions.
How I make the grid loads this data into it?
Best Regards,
I'll do something among these lines:
...//This is the form onsuccess
succes: function(response) {
var json = Ext.JSON.decode(response.responseText);
var win Ext.create('Ext.window.Window', {
width: 600,
height: 400,
items: [ {
xtype:'grid',
columns:[ ... ],
store: Ext.create('Ext.data,Store',{
fields: ['field1', 'field2'],
data: json })
}]
});
win.show();
}
Hope that helps.