I'm stuck trying to pass JSON to a dataTable.
I load JSON at a different point in the script, then truncate the part I need and pass it into a function that is supposed to render the table.
The function is:
function populateCasesTable(d){
var json = d.cases;
var cols = [
{ "data" : json.service_area},
{ "data" : json.presenting_issue },
{ "data" : json.referred_by },
{ "data" : json.date_opened },
{ "data" : json.case_status },
{ "data" : json.preferred_staff }
];
console.log(json);
$('#cases_table').DataTable( {
"data": json,
"columns": cols
} );
}
HTML for the table is
<table id='cases_table' width="100%">
<thead>
<tr>
<th>Service Area</th>
<th>Presenting Issue</th>
<th>Referred by</th>
<th>Date opened</th>
<th>Status</th>
<th>Preferred Staff</th>
</tr>
</thead>
</table>
The console.log output returns the right amount of objects (12) and a single object looks eg:
0 Object:
action:9
case_status:"Open"
date_created:"11/07/2017"
date_opened:"11/07/2017"
file:5
id:31646
issues:8
preferred_staff:"Doc Kuran"
presenting_issue:"Anxiety Disorder"
referral:0
referred_by:"Academic staff"
serviceAreaId:14
service_area:"Disability Services"
staff:0
I get the right number of pages rendered accompanied by the cryptic 'DataTables warning: table id=cases_table - Requested unknown parameter '0' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4' pop-up.
I'm sure this is a config issue, but I could not work this out.
What am I missing?
Thanks.
I found it. Cols must be set as follows:
var cols = [
{ "data" : 'service_area'},
{ "data" : 'presenting_issue' },
{ "data" : 'referred_by' },
{ "data" : 'date_opened' },
{ "data" : 'case_status' },
{ "data" : 'preferred_staff' }
];
Related
I have read plenty of resources and questions here regarding nested JSON but none are asking the exact same.
I am trying to use IBM Instana to retrieve the page load metrics what I plan to load into a JQUERY DataTables table.
The nested JSON I get from Instana:
{
"items" : [ {
"name" : "/Content/Search.htm",
"earliestTimestamp" : 1674432701496,
"cursor" : {
"#class" : ".IngestionOffsetCursor",
"ingestionTime" : 1674509519588,
"offset" : 1
},
"metrics" : {
"pageLoads.sum" : [ [ 1674511200000, 79.0 ] ]
}
}, {
"name" : "/Content/Home.htm",
"earliestTimestamp" : 1674435256403,
"cursor" : {
"#class" : ".IngestionOffsetCursor",
"ingestionTime" : 1674509519588,
"offset" : 2
},
"metrics" : {
"pageLoads.sum" : [ [ 1674511200000, 45.0 ] ]
}
} ],
"canLoadMore" : false,
"totalHits" : 2,
"totalRepresentedItemCount" : 2,
"totalRetainedItemCount" : 2,
"adjustedTimeframe" : {
"windowSize" : 169200000,
"to" : 1674511200000
}
}
and the code to load it and add it to a table in DataTables:
$(document).ready(function () {
$('#example').DataTable({
ajax: {
url: 'data/daily.txt',
dataSrc: 'items',
},
columns: [
{ data: 'cursor.offset' },
{ data: 'name' },
{ data: 'earliestTimestamp' },
{ data: 'metrics[0]' },
],
deferRender: true
});
});
While the whole thing is straightforward, even the nested cursor.offset with the dot, I fail to assign the two value in metrics\pageLoads.sum, especially that the nested pageLoads.sum also contains a dot and the values are in double square brackets without quotation marks. The two values (date and number of page loads) I would like to have in two separate columns, but as fail to load them at all, I went on to load them somehow into one cell, but even that does not work.
I have tried to add pageLoads.sum (then as 'metrics."pageLoads.sum"')in quotes, but didn't help, DataTables threw the error message "Requested unknown parameter 'metrics.....<and the variation I have tried>.
I have also tried:
{ data: 'metrics' }, this returns [object Object] in the html cells
{ data: 'metrics[0]' }, no error from DT, but cell remains empty
{ data: 'metrics[, ]' },no error from DT, but cell remains empty
Is there any way to access the two values within metrics\pageLoads.sum or do I have to change JSON structure before this can be done?
To split the contents of your nested arrays...
"pageLoads.sum" : [ [ 1674511200000, 45.0 ] ]
...into two columns, you can use the following:
columns: [
{ data: 'cursor.offset' },
{ data: 'name' },
{ data: 'earliestTimestamp' },
{
data: 'metrics.pageLoads\\.sum',
render: function (data, type, row) {
return data[0][0];
}
},
{
data: 'metrics.pageLoads\\.sum',
render: function (data, type, row) {
return data[0][1];
}
}
]
This uses the double-backslash I mentioned in a comment (ref.) and also two column renderers which handle the splitting of the nested arrays into 2 separate fields.
The end result looks like this:
I have tried looking for a solution, but the closest I cold find were with adding a simple key with a value...
So, I have this Json object:
{
"answers": [
{
"phrase": "Why?",
"nextIntentId": "4a10fd2b-bc6b-4563-8d97-34ef6dec1ba9"
},
{
"phrase": "Faster recovery?",
"nextIntentId": "4f9eeecf-6477-435b-9f1b-43304748a4e5"
}
],
"intentId": "19f458e8-ce1f-43eb-beb8-b8ef4e7ff4c7"
}
And I want to add an array to this object:
"messages" : []
The idea is, that afterwards I can intent.messages.push(object) objects to this array, just like in the "answers" : [] array
{
"answers": [
{
"phrase": "Why?",
"nextIntentId": "4a10fd2b-bc6b-4563-8d97-34ef6dec1ba9"
},
{
"phrase": "Faster recovery?",
"nextIntentId": "4f9eeecf-6477-435b-9f1b-43304748a4e5"
}
],
"intentId": "19f458e8-ce1f-43eb-beb8-b8ef4e7ff4c7",
"messages" : [] <<------------ I want to add this aray
}
I have also tried object.push('messages[]') and got Error: this.intent.push is not a function
Thankyou for any kind of help in advance!
You can set the value directly to a blank array:
this.intent.messages = [];
I'm working on a chemicals database web application. Using DataTables 1.10.16 and CakePHP 3.5
Cake is producing a JSON feed. A sample is below:
[
{
"id": 1,
"app_id": "ID000001",
"name": "Chromium",
"ecs": [
{
"id": 1,
"value": "123-456-7"
},
{
"id": 32,
"value": "222-333-444"
},
],
"cas": [
{
"id": 1,
"value": "987-654-3"
}
]
},
]
For certain chemicals there are multiple EC (ecs in the JSON) and CAS Numbers (cas in the JSON).
I don't know if/how it's possible to get DataTables to loop through these objects, outputting them in the appropriate columns, with a separator such as a <br> tag.
My table markup looks like this:
<table id="substancesTable" class="table responsive display table-striped" cellspacing="0" width="100%">
<thead>
<tr>
<th>Application ID</th>
<th>EC Number</th>
<th>CAS Number</th>
<th>Chemical Name</th>
</tr>
</thead>
</table>
And in my Javascript I'm doing this:
$('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url" : "/get-substances.json",
"method" : "POST",
"dataSrc":""
},
"columns": [
{ "data": "app_id", "name" : "app_id" },
{ "data": "ecs", "name" : "ec_number" },
{ "data": "cas", "name" : "cas_number" },
{ "data": "name", "name" : "name" },
]
});
This works in terms of populating the "Application ID" and "Chemical Name" columns - but that's because there is a simple 1:1 mapping in the JSON (no arrays/objects).
The output for the "EC Number" and "CAS Number" columns is just [object Object] and is repeated the number of objects there are. In the example above there are 2 EC Numbers for this chemical so the output under "EC Number" is [object Object],[object Object]
Can anyone assist with this? I'd like the output to be generated by looping through my JSON and introducing a break between each item, e.g.
123-456-7<br>222-333-444
You'll be needing a render function like this:
{
"data": "ecs",
"name": "ec_number",
"title":"EC Number",
"render": function(d,t,r){
return d.map(function(e) {
return e.value;
}).join("<br/>");
}
}
Working JSFiddle here.
I am using DataTables ajax to fill a table. I was following this example and it works if my json looks like their example, however my 'data' is a nested object in my json and then it is not able to fill the table because fails in getting the values from the json.
This json works:
{
"data": [
{"id": "myid1", "name": "name1"},
{"id": "myid2", "name": "name2"}
]
}
But my json looks like this, and it does not work
{
"result": {
"data": [
{"id": "myid1", "name": "name1"},
{"id": "myid2", "name": "name2"}
]
}
}
That's my html (which works with the first json):
<table id="myTable" class="tabletable-bordered dataTable">
<thead>
<tr>
<th>name</th>
<th>id</th>
</tr>
</thead>
<tbody>
<td></td>
<td></td>
</tbody>
</table>
And that's my js:
$('#myTable').DataTable( {
"ajax": "/names",
"processing": true,
"dataSrc" : "result.data",
"columns": [
{ "data": "name" },
{ "data": "id" }
]
} );
As you can see I try to access to my nested data by setting dataSrc to result.data, but nothing is shown in the table.
I cannot change the format of the json response, do you know if then is not possible to use DataTables ajax with this json? Thanks!
MY SOLUTION
Finally (before getting an answer to my post) I went with the following solution, I first make an ajax call and then on success I create my DataTable.
so I only changed my js to this one:
$.ajax({
type: "GET",
url: '/names',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
var myData = data.result.data;
$('#myTable').DataTable({
"data": myData,
"columns": [
{ "data": "id" },
{ "data": "name"},
]
});
}
});
I had more complex processing requirements so I implemented my own ajax function but I think you can get away with this:
$('#myTable').DataTable( {
"processing": true,
"ajax": {
"url": "/names",
"dataSrc" : function(jsonObj) {
// Just being safe here
if(!jsonObj.results || !json.results.data) {
return [];
}
return jsonObj.results.data;
}
},
"columns": [
{ "data": "name" },
{ "data": "id" }
]
});
Here is the reference for this: https://datatables.net/reference/option/ajax
My two JSON arrays are,
$scope.myHospital = [
{"id":"1","name":"hos1"},
{"id":"2","name":"hos2"},
{"id":"3","name":"hos3"},
{"id":"4","name":"hos4"},
{"id":"5","name":"hos5"}
];
another one is
$scope.data = [
{
"category":"first category",
"procedure":[{
"name":"pro1",
"hospital": [
{"id":"1","price":"1101"},
{"id":"2","price":"1102"},
{"id":"3","price":"1103"},
{"id":"4","price":"1104"},
{"id":"5","price":"1105"}
]
}, {
"name":"pro2",
"hospital": [
{"id":"1","price":"1201"},
{"id":"2","price":"1202"},
{"id":"3","price":"1203"},
{"id":"4","price":"1204"},
{"id":"5","price":"1205"}
]
}, {
"name":"pro3",
"hospital": [
{"id":"1","price":"1301"},
{"id":"3","price":"1303"},
{"id":"5","price":"1305"}
]
}]
},
{
"category":"Second category",
"procedure":[{
"name":"pro4",
"hospital": [
{"id":"1","price":"2101"},
{"id":"2","price":"2102"},
{"id":"3","price":"2103"},
{"id":"4","price":"2104"},
{"id":"5","price":"2105"}
]
}, {
"name":"pro5",
"hospital": [
{"id":"1","price":"2201"},
{"id":"2","price":"2202"},
{"id":"4","price":"2204"}
]
}]
}
];
BY these I want a table like this
I tried it by ng-repeat till now I manage to generate the table here in plnkr
Now I stuck on the logic of null values by matching the hospital id. Inserting null values manually in JSON will not work for me because I am getting this JSON from backend. But I can ask them to change JSON structure(format of array) if needed.
Try smart table. https://github.com/lorenzofox3/Smart-Table
Our prepare your data before ng-repeat to fit your needs.
Not The Exact Solution But May Be Helpful..
<table border="2">
<tbody ng-repeat="cat in data">
<tr>
<td>{{cat.category}}</td>
</tr>
<tr ng-repeat="procedure in cat.procedure">
<td>{{procedure.name}}</td>
<td ng-repeat="hospital in procedure.hospital">{{hospital.price}}</td>
</tr>
</tbody>
Here is the working code.
I have made a bit of changes in your data source too which is easy to consider and make and in HTML too.
In your plunker you were displaying wrong value corresponding to the hospitals when there are few records present in "hospital" object in $scope.data.To rectify that I have added null objects too so the ng-repeat will pass right index for comparision to display
In JS
$scope.data = [
{
"category":"first category",
"procedure":[{
"name":"pro1",
"hospital": [
{"id":"1","price":"1101"},
{"id":"2","price":"1102"},
{"id":"3","price":"1103"},
{"id":"4","price":"1104"},
{"id":"5","price":"1105"}
]
}, {
"name":"pro2",
"hospital": [
{"id":"1","price":"1201"},
{"id":"2","price":"1202"},
{"id":"3","price":"1203"},
{"id":"4","price":"1204"},
{"id":"5","price":"1205"}
]
}, {
"name":"pro3",
"hospital": [
{"id":"1","price":"1301"},
{"id":"2","price":null}, // add null objects for considering right index in display...
{"id":"3","price":"1303"},
{"id":"4","price":null},
{"id":"5","price":"1305"}
]
}]
},
{
"category":"Second category",
"procedure":[{
"name":"pro4",
"hospital": [
{"id":"1","price":"2101"},
{"id":"2","price":"2102"},
{"id":"3","price":"2103"},
{"id":"4","price":"2104"},
{"id":"5","price":"2105"}
]
}, {
"name":"pro5",
"hospital": [
{"id":"1","price":"2201"},
{"id":"2","price":"2202"},
{"id":"3","price":null},
{"id":"4","price":"2204"},
{"id":"5","price":null}
]
}]
}
];
In your HTML
<tr ng-repeat="(index, hos) in myHospital">
<td width="100px">{{hos.name}}</td>
<td width="100px" ng-repeat="pro in d.procedure">
<p ng-show="pro.hospital[index].id == index+1">{{ pro.hospital[index].price }}</p>
<p ng-hide="pro.hospital[index].id == index+1 && pro.hospital[index].price">NULL</p>
</td>
</tr>
You can change the JSON structure after receiving it in order to make it renderable on UI. Something like this,
angular.forEach($scope.data[0].procedure, function(pro) {
var arr = [];
angular.forEach(pro.hospital, function(hos) {
arr[hos.id] = hos.price
});
pro.hospital = arr;
});
Now your hospital array that has lesser values would look like following. If you notice, I changed the structure from array of objects to an array of strings having prices with keys denoting the hospital number..
hospital: [
2: "469",
3: "429",
5: "319"
]
Finally, you can have your rendering logic like following for embracing this change,
<tr ng-repeat="(index, hos) in myHospital">
<td ng-bind="hos.name"></td>
<td ng-repeat="pro in data[0].procedure">
<span ng-bind="pro.hospital[index+1]"></span>
<span ng-if="!pro.hospital[index+1]">NULL</span> <!--Optional-->
</td>
</tr>
DEMO