I am building a site which will output data from a JSON file into a table, but I am having issues getting the content to output. This JSON file is generated from another site which surfaces documentation, while my site just creates a table for easy searching of those docs.
SAMPLE JSON for 2 docs:
[{
"title": "SampleTitleA",
"lang": "en-US",
"lastEdition": "2020-07-28",
"version": "1.0",
"metadata": [
{
"key": "sampleKeyA1",
"label": "sampleLabelA1",
"values": ["sampleValueA1"]
},
{
"key": "sampleKeyA2",
"label": "sampleLabelA2",
"values": ["sampleValueA2"]
}]
},
{
"title": "SampleTitleB",
"lang": "en-US",
"lastEdition": "2020-07-28",
"version": "1.0",
"metadata": [
{
"key": "sampleKeyB1",
"label": "sampleLabelB1",
"values": ["sampleValueB1"]
},
{
"key": "sampleKeyB2",
"label": "sampleLabelB2",
"values": ["sampleValueB2"]
}]
}]
I am using DataTables for this (https://datatables.net/examples/ajax/deep.html) and have tried doing what it describes. It doesnt really cover reading arrays within arrays though.
To select an array within an array I have tried to follow the datatables example and done the following:
$(document).ready(function() {
$('#example').DataTable({
//sort on col 3 desc
"order": [3, 'desc'], //order by date
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
"ajax": {
"type": 'GET',
"dataType": 'json',
"lengthChange": true,
"contentType": 'application/json; charset=utf-8',
"url": "jsonlocation",
"deferRender": true,
"dataSrc": ""
},
"buttons": [ 'copy', 'excel',
{ extend: 'colvis', columns: [0,1,2,3,4,5,6]}
],
"dom": 'Bfrtip',
"columns": [
{ data: 'metadata.15.values.0', "defaultContent": "-" },
{ data: 'title', "defaultContent": "-" },
{ data: 'metadata.16.values.0', "defaultContent": "-" },
{ data: 'lastEdition', "defaultContent": "-" },
{ data: 'lang', "defaultContent": "-" },
{ data: 'version', "defaultContent": "-" },
{ data: 'readerUrl', "defaultContent": "-" },
{ data: 'readerUrl', "defaultContent": "-" },
],
"columnDefs": [{
"targets": [5],
"render": function(data, type, row, meta) {
return 'Click';
}
},
{
"targets": [7],
"visible": false,
"searchable": true
}
]
});
}
);
A table is created, but not populated, and shows no errors in console.
Has anyone any experience using dataTables for this purpose?
Thanks
Check if this helps you out.
var data = {
"title": "SampleTitle",
"lang": "en-US",
"lastEdition": "2020-07-28",
"version": "1.0",
"metadata": [
{
"key": "sampleKey1",
"label": "sampleLabel1",
"values": ["sampleValue1"]
},
{
"key": "sampleKey2",
"label": "sampleLabel2",
"values": ["sampleValue2"]
}]
}
var result = { data: data.metadata[1].values[0], "defaultContent": "-" }
console.log(result);
Your JSON data structure is an array - everything is contained in a [...] - therefore DataTables can iterate over this array to generate its table rows.
Here is an example with everything removed from your code except for the column data definitions (and column titles):
<script type="text/javascript">
$(document).ready(function() {
$('#example').DataTable({
ajax: {
// my test URL:
url: 'http://localhost:7000/sample2',
dataSrc: ''
},
"columns": [
{ title: 'Title', data: 'title' },
{ title: 'Language', data: 'lang' },
{ title: 'Key', data: 'metadata[0].key' },
{ title: 'Label', data: 'metadata[0].label' },
{ title: 'First Value', data: 'metadata[0].values[0]' }
]
} );
} );
</script>
This generates a table which looks like this:
How does this work?
By default, DataTables expects the JSON structure to be as one of the following:
An object containing an array of other objects:
{ "data": [ {...},{...},... ] }
An object containing an array of arrays:
{ "data": [ [...],[...],... ] }
In both these cases, the array has a name (in this case data).
In your case, as already noted, your data is just a plain array of objects:
[ {...}, {...},... ]
Because the array has no name, we need to use dataSrc: '' in our DataTable definition, to indicate this lack of a name.
After that, you can reference the values you need to display, for example data: 'title'.
For the metadata section, that is itself a label referring to an array of objects:
"metadata": [ {...} ]
However, in this case the array only contains one object. We can refer to that first object in the metadata array using [0] - and then we can access the values in that object - for example, by using: data: 'metadata[0].label'.
Related
I am having a JSON file with the following values and I am trying to fill the DataTable with the values of the JSON file.
I would like the DataTable to be of the format with 3 columns (Color, Size, Quantity).
An example would be Red, Small, 100 and Red, Medium, 200.
However, these 3 columns are within the JSON object "invSelectionCount" as shown in my JSON file. How do I iterate through the JSON file to manipulate the object within it to fill up the DataTable?
AJAX Call
$.ajax({
'url': 'http://localhost:8080/Retail-war/webresources/products/getProduct/' + productId,
'method': 'GET',
'contentType': 'application/json; charset=utf-8',
'headers': {"Authorization": 'Bearer ' + sessionStorage.getItem('accessToken')},
}).done( function(data) {
$('#product-inventory-level').DataTable( {
"data": [data],
"columns": [
{ "data": "invSelectionCount"},
{ "data": "invSelectionCount"},
{ "data": "invSelectionCount"}
],
})
})
JSON File
{
"productId": 1,
"originalPrice": 59.9,
"currentPrice": null,
"productStatus": "LISTED",
"discount": null,
"productVol": null,
"invSelectionCount": {
"red=small": 100,
"red=medium": 200
},
}
You can use map on keys of invSelectionCount to return desired object
Object.keys(data["invSelectionCount"]).map(key =>{return {
Color: key.split('=')[0],
Size: key.split('=')[1],
Quantity: data["invSelectionCount"][key]
}})
Run this snippet
let data={
"productId": 1,
"originalPrice": 59.9,
"currentPrice": null,
"productStatus": "LISTED",
"discount": null,
"productVol": null,
"invSelectionCount": {
"red=small": 100,
"red=medium": 200 }
}
$('#product-inventory-level').DataTable({
"columns": [{
"title": "Color",
"data": "Color",
},
{
"title": "Size",
"data": "Size"
},
{
"title": "Quantity",
"data": "Quantity"
}
],
"data": Object.keys(data["invSelectionCount"]).map(key =>{return {
Color: key.split('=')[0],
Size: key.split('=')[1],
Quantity: data["invSelectionCount"][key]
}})
})
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" >
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<table id="product-inventory-level"></table>
Try to expand this:
.done( function(data) {
var array = new Array();
Object.keys(json["invSelectionCount"]).forEach(function(key) {
var splitstring = key.split('=');
splitstring[0] -> red
splitstring[1] -> small
json["invSelectionCount"][key] -> 100
array.push({"color": splitstring[0], "size": splitstring[1], "quantity": json["invSelectionCount"][key],});
});
$('#product-inventory-level').DataTable( {
"data": [array],
"columns": [
{ "data": "color"},
{ "data": "size"},
{ "data": "quantity"}
],
})
})
I am trying to display data and view/edit/delete buttons using datatables.
I am getting user data and permission using two objects like this:
]
{
"data": [
{
"userid": "1",
"username": "John",
"email": "john#gmail.com",
"userrole": "SYSTEM VENDOR",
"isactive": "Y",
"activationstat": "deactivate",
"activationmsg": "Deactivate"
}
],
"perm":
{
"read": "y",
"edit": "y",
"delete": "n"
}
}
The button needs to be rendered for each row. Datatables code is as:
$('#dt-user').DataTable({
dom: 'lBfrtip',
buttons: [
{
extend: 'copyHtml5',
exportOptions: {
columns: ':visible'
}
},
{
extend: 'csvHtml5',
exportOptions: {
columns: ':visible'
}
},
{
extend: 'excelHtml5',
exportOptions: {
columns: ':visible'
}
},
{
extend: 'pdfHtml5',
exportOptions: {
columns: ':visible'
}
},
{
extend: 'print',
exportOptions: {
columns: ':visible'
}
},
'colvis'
],
ajax: baseURL + 'user/list-user-aj',
columns: [
{
"data": "id",
render: function (data, type, row, meta) {
return meta.row + meta.settings._iDisplayStart + 1;
}
},
{ data: 'username' },
{ data: 'email' },
{ data: 'userrole' },
{ data: 'isactive' }
],
responsive: {
details: false
}
});
How can I access the "perm" JSON object for checking its values for displaying buttons for edit, delete, print etc?
Short answer: You will not be able to get "perm" object within datatables initialization code. Datatables initialization code only works with "data" array from JSON.
However, here are two possible solutions to your situation:
Option 1:
If the "perm" object is going to be common for all elements (users) in the "data" array in JSON, like follows:
{
"data": [
{
"userid": "1",
"username": "John",
"email": "john#gmail.com",
"userrole": "SYSTEM VENDOR",
"isactive": "Y",
"activationstat": "deactivate",
"activationmsg": "Deactivate"
},
{
"userid": "2",
"username": "John2",
"email": "john2#gmail.com",
"userrole": "SYSTEM VENDOR2",
"isactive": "Y",
"activationstat": "deactivate",
"activationmsg": "Deactivate"
}
<!-- and maybe some more objects-->
],
"perm":
{
"read": "y",
"edit": "y",
"delete": "n"
}
}
then you can access the perm object like below: (and that would be outside of Datatables definition)
var permissions;
userDatatable.on('xhr', function () {
var json = userDatatable.ajax.json();
var permissions = json.perm;
});
where userDatatable will be the global javascript variable when you initialize Datatables like below:
var userDatatable = $('#dt-user').DataTable({ //......and all your code
Then inside your columns definition, you can access perm object and render buttons like this:
columns:[
{
data:null,
"render": function(data, type, row, meta){
if(perm.delete === 'y'){
return "<button class='deleteButton'> Delete </button>";
}
}
}
]
Make sure javascript variable "permissions" is global and visible to your Datatables initialization code. This will get you the Delete button, but you will have to write additional Javascript/JQuery code to trigger the Datatables Editor's AJAX call to delete the row; both at backend and from the grid.
Option 2: You could modify your server-side code to return JSON such that it will have permissions object within each element of the "data" array:
{
"data": [
{
"userid": "1",
"username": "John",
"email": "john#gmail.com",
"userrole": "SYSTEM VENDOR",
"isactive": "Y",
"activationstat": "deactivate",
"activationmsg": "Deactivate",
"perm":
{
"read": "y",
"edit": "y",
"delete": "n"
}
},
{
"userid": "2",
"username": "John2",
"email": "john2#gmail.com",
"userrole": "SYSTEM VENDOR2",
"isactive": "Y",
"activationstat": "deactivate",
"activationmsg": "Deactivate",
"perm":
{
"read": "y",
"edit": "y",
"delete": "n"
}
}
<!-- and maybe some more objects-->
]
}
With this second option, you could access perm object within the "render" function using "row.perm.delete" property.
Hope this help!
Say i have an array as the data source for DataTables, delivered through AJAX
{
"data": [
[
"https://stackoverflow.com/questions/ask",
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421",
"2011/04/25",
"$320,800"
]
]
}
I want to ignore the first cell and not output it as a column, so how can i map the indexed data to the columns? I have already tried this, but it gives an error:
$(document).ready(function() {
$('#example').DataTable( {
"ajax": "data/objects.txt",
"columns": [
{ "data": [1] },
{ "data": [2] },
{ "data": [3] },
{ "data": [4] },
{ "data": [5] },
{ "data": [6] }
]
} );
} );
Uncaught TypeError: Cannot read property 'mData' of undefined
I also tried to reference the indexes like this
"data": 1
Doesn't work either.
If the source was an Object with keys, referencing would work like this:
"columns": [
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "extn" },
{ "data": "start_date" },
{ "data": "salary" }
]
I managed to find a solution myself, this code will make the first cell invisible and display the other cells:
$(document).ready(function() {
$('#example').DataTable( {
"ajax": "data/objects.txt",
"columnDefs": [
{ "targets": [0], "visible": false },
{ "targets": '_all', "visible": true }
]
} );
} );
var obj = {}
var keys = ['name', 'job', 'location', 'number', 'date', 'salary']
var arr = [
'https://stackoverflow.com/questions/ask',
'Tiger Nixon',
'System Architect',
'Edinburgh',
'5421',
'2011/04/25',
'$120000'
]
.filter((item, i) => !!i)
.forEach((v, i) => obj[keys[i]] = v)
console.log(obj)
I am using jquery DataTables to bind my JSON data to the Table, however when I specify the JSON object to the 'aaData' option of the DataTable, it throws me this error:
"DataTables warning (table id = 'tblReceipt'): Requested unknown parameter '1' from the data source for row 0"
My JSON object looks like this:
var r = [
{ "Vid": "1", "Receiptno": "AFL123", "Type": "3", "Branch": "AFL", "Date": "23/11/2013" },
{ "Vid": "2", "Receiptno": "AFL124", "Type": "4", "Branch": "AFL", "Date": "24/11/2013" },
{ "Vid": "3", "Receiptno": "AFL125", "Type": "6", "Branch": "AFL", "Date": "25/11/2013" },
];
I am passing it to DataTables like this:
$("#tblReceipt").dataTable({
"aaData": JSON.stringify(r),
"bJQueryUI": true,
"bDestroy": true,
"iDisplayLength": 50,
"bProcessing": true,
"aaSorting": [[0, 'desc']],
"aoColumns": [
{ "mData": "Vid" },
{ "mData": "Receiptno" },
{ "mData": "Type" },
{ "mData": "Branch" },
{ "mData": "Date" },
],
"oLanguage": {
"sProcessing": "Fetching Data, Please wait..."
},
});
Any help would be greatly appreciated!
Just replace "aaData": JSON.stringify(r), with "aaData": r,.
Working demo: http://jsfiddle.net/qMPzh/1/
I'm having the following issue while using Flot for a graph. The input for the graph is JSON, retrieved from a server.
The ajax call to get the data is:
$.ajax({
url: 'graphdata.do',
dataType: 'json',
success: function (retData) {
renderGraph(retData);
}
});
And the renderGraph function:
function renderGraph(datasets)
{
var data = [];
console.log(datasets);
$('.cbScenarioSelected').each(function(index) {
if($(this).is(':checked')){
var id = $(this).prop("id"); //this works, right id is returned
data.push(datasets[id]);
}
});
$.plot($("#graph1"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 }
});
}
The data returned from the server:
{
"1": {
"label": "Name1",
"data": "[[133,64.8000030517578],[134,64.8099975585938],[135,65.0999984741211],[136,66.0699996948242],[137,66.129997253418],[138,66.2600021362305],[139,66.6699981689453],[140,66.9400024414063],[141,67.4100036621094],[142,68.0599975585938], [143,68.0800018310547],[144,68.3600006103516],[145,68.8699951171875], [146,69.4899978637695],[147,69.6500015258789],[148,70.0999984741211], [149,70.7400054931641],[150,70.9199981689453],[151,71.1500015258789], [152,71.7000045776367],[153,72.0899963378906],[154,72.4799957275391], [155,73.2700042724609],[156,73.3000030517578],[157,73.4599990844727], [158,73.5100021362305],[159,74.6799926757813],[160,77.5200042724609], [161,77.8399963378906],[162,78.8300018310547]]"
},
"2": {
"label": "Name2",
"data": "[]"
},
"3": {
"label": "Name3",
"data": "[]"
}
}
The graph container is shown, and so are the labels. The lines in the graph are not shown.
Anyone have an idea? I think it has something to do with the quotes around the "data" tag in the returned data, but I have no idea how to fix it.
In your JSON, data part are string because of they are encapsulated with quotes.
In fact, the json should look like (without quotes)
{
"1": {
"label": "Name1",
"data": [
[
133,
64.8000030517578
],
[
134,
64.8099975585938
],
[
135,
65.0999984741211
],
[
136,
66.0699996948242
],
[
137,
66.129997253418
],
...
]
},
"2": {
"label": "Name2",
"data": []
},
"3": {
"label": "Name3",
"data": []
}
}