How to get data from nested array in DataTables? - datatables

I used to download data from a json file in this format to my DataTables table:
{
"data": [
["n/a","668","01.11.2021 14:16:20", ... ],
["n/a","670","05.11.2021 23:23:54", ...]
]
}
...
"ajax": "first.json",
columns: [
{ data: 0 },
{ data: 1 }
...
And everythig was ok
But now format of my json was changed:
{
"data": {
"deals": [["n/a", "718", "30/11/2021 21:46:14"], ["", "718", "30/11/2021 21:46:14"], ... ],
"stops": [["07/10/2021 21:48:28", "BTCUSDT"], ["07/10/2021 21:48:28", "BTCUSDT"], ... ]
}
}
And I try to get data like this and get "No data available in table":
...
"ajax": "first.json",
columns: [
{ data: 'deals.0' },
{ data: 'deals.1' }
...
How can I get data from new format of json to my table?

Here is your new JSON structure, provided by the URL:
{
"data": {
"deals": [
["n/a", "718", "30/11/2021 21:46:14"],
["", "718", "30/11/2021 21:46:14"]
],
"stops": [
["07/10/2021 21:48:28", "BTCUSDT"],
["07/10/2021 21:48:28", "BTCUSDT"]
]
}
}
In this structure, the location of the deals data is data.deals. This location points to an array of arrays, which is what DataTables needs (or an array of objects).
(This means the table will only have access to the deals data, since the stops data is in a separate location entirely. But I will assume you only want the deals data to match your original example.)
You therefore need to use the DataTables dataSrc option to tell DataTables where to look in your new JSON:
<table id="example" class="display" style="width:100%"></table>
and:
$(document).ready(function() {
$('#example').DataTable( {
ajax: {
method: "GET",
url: "first.json", // or whatever URL you want to use
dataSrc: "data.deals"
},
"columns": [
{ "title": "Col 1" },
{ "title": "Col 2" },
{ "title": "Col 3" }
]
} );
} );
Because each row of data is an array, you don't need to specify the specific array indexes in your columns - DataTables will iterate over each row array for you.
The result is:

Related

Get JSON Array from JSON Object and Count Number of Objects

I have a column that contains some data like this:
{
"activity_goal": 200,
"members": [
{
"json": "data"
},
{
"HAHA": "HAHA"
},
{
"HAHA": "HAHA"
}
],
"name": "Hunters Team v3",
"total_activity": "0",
"revenue_goal": 200,
"total_active_days": "0",
"total_raised": 300
}
I am using cast(team_data -> 'members' as jsonb) to get the "Members" JSON array, which gives me a column like this:
[
{
"json": "data"
},
{
"HAHA": "HAHA"
},
{
"HAHA": "HAHA"
}
]
I am using array_length(cast(team_data -> 'members' as jsonb), 1) to pull a column with the number of Members that exist in the list. When I do this, I am given this error:
function array_length(jsonb, integer) does not exist
Note: I have also tried casting as "json" instead of "jsonb"
I am following this documentation. What am I doing wrong?
Use the JSON functions when working with json such as json_array_length
select json_array_length(team_data -> 'members') from mytable

express-graphql: How to remove external "data" object layer.

I am replacing an existing REST endpoint with GraphQL.
In our existing REST endpoint, we return a JSON array.
[{
"id": "ABC"
},
{
"id": "123"
},
{
"id": "xyz"
},
{
"id": "789"
}
]
GraphQL seems to be wrapping the array in two additional object layers. Is there any way to remove the "data" and "Client" layers?
Response data:
{
"data": {
"Client": [
{
"id": "ABC"
},
{
"id": "123"
},
{
"id": "xyz"
},
{
"id": "789"
}
]
}
}
My query:
{
Client(accountId: "5417727750494381532d735a") {
id
}
}
No. That was the whole purpose of GraphQL. To have a single endoint and allow users to fetch different type/granularity of data by specifying the input in a query format as opposed to REST APIs and then map them onto the returned JSON output.
'data' acts as a parent/root level container for different entities that you have queried. Without these keys in the returned JSON data, there won't be any way to segregate the corresponding data. e.g.
Your above query can be modified to include another entity like Owner,
{
Client(accountId: "5417727750494381532d735a") {
id
}
Owner {
id
}
}
In which case, the output will be something like
{
"data": {
"Client": [
...
],
"Owner": [
...
]
}
}
Without the 'Client' and 'Owner' keys in the JSON outout, there is no way to separate the corresponding array values.
In your case, you can get only the array by doing data.Client on the returned output.

How DataTables determine columns type

I have a dynamic table enhanced by jQuery DataTables, which display a custom object similar to this example.
JSON:
{
"data": [
{
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": {
"display": "SomeString",
"timestamp": 1303686000
},
"office": "Edinburgh",
"extn": "5421"
},
// ... skipped ...
]}
JavaScript:
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: {
_: "start_date.display",
sort: "start_date.timestamp"
} },
{ data: "salary" }
]
} );
} );
The difference is that I dynamically build the columns configuration, because the columns can be in any order, and others columns can be added or removed from the list. For this example (my case is very similar) the problem is that for some reason the timestamp property is ordered as a String instead of being ordered as a number.
I discovered that after setting the column "type" as "number" the ordering works perfectly. I'm presuming that DataTables is auto detecting the column as "String" for some reason (maybe because the display element is a string).
How does DataTables set the type of the columns, when is not explicitly declared?
Edit 1
I made a sample code to show the problem
http://jsfiddle.net/Teles/agrLjd2n/16/
jQuery DataTables has built-in mechanism for type detection. There are multiple predefined functions for various types with fallback to string data type.
It's also possible to use third-party plug-ins or write your own.
There are multiple ways to specify data type, below are just the few.
SOLUTION 1
Use type option.
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: "start_date.display", type: "date" },
{ data: "salary" }
]
} );
} );
SOLUTION 2
Use returned JSON data for type detection, see columns.data for more information.
$(document).ready(function() {
$('#example').DataTable( {
ajax: "data/orthogonal.txt",
columns: [
{ data: "name" },
{ data: "position" },
{ data: "office" },
{ data: "extn" },
{ data: {
_: "start_date.display",
sort: "start_date.timestamp",
type: "start_date.timestamp",
} },
{ data: "salary" }
]
} );
} );
DataTables always check the "type" property of the column "data" to auto detect the type of the column, if no "type" property is specified it will check the default value "_".
So if you want DataTables to auto detect the type of the column checking the type of your "sort" property you should set the "type" property of data to be equals to your "sort" value
Here is a sample code with different approchs to achieve what I was tryng to do. Thanks #Gyrocode.com and #davidkonrad.
var Cell = function(display, value) {
this.display = display;
this.value = value;
}
$(document).ready(function() {
var cells = [
new Cell("120 (10%)", 120),
new Cell("60 (5%)", 60),
new Cell("30 (2.5%)", 30)
];
$('#example').DataTable( {
data: cells,
columns: [
{
title : "Column NOT OK",
data: {
_: "display",
sort: "value"
}
}, {
type : "num",
title : "Column Ok setting column type",
data: {
_: "display",
sort: "value"
}
}, {
title : "Column Ok changing default value",
data: {
_: "value",
display: "display",
filter: "display"
}
}, {
title : "Column Ok setting data type",
data: {
_: "display",
sort: "value",
type: "value"
}
}, {
type : "num",
title : "Column Not OK",
data: "display"
}
]
} );
} );

DataTables ajax requires explicit json collection name for the returned datasource?

I recently ran into a problem when implementing the ajax functionality of jquery DataTables. Until I actually gave my json object collection an explicit name I couldn't get anything to display. Shouldn't there be a default data source if nothing named is returned?
Client Side control setup (includes hidden field that supplies data to dynamic anchor:
$('#accountRequestStatus').dataTable(
{
"destroy": true, // within a method that will be called multiple times with new/different data
"processing": true,
"ajax":
{
"type": "GET",
"url": "#Url.Action("SomeServerMethod", "SomeController")",
"data": { methodParam1: 12341, methodParam2: 123423, requestType: 4123421 }
}
, "paging": false
, "columns": [
{ "data": "DataElement1" },
{ "data": "DataElement2", "title": "Col1" },
{ "data": "DataElement3", "title": "Col2" },
{ "data": "DataElement4", "title": "Col3" },
{ "data": "DataElement5", "title": "Col4" },
]
, "columnDefs": [
{
"targets": 0, // hiding first column, userId
"visible": false,
"searchable": false,
"sortable": false
},
{
"targets": 5, // creates action link using the hidden data for that row in column [userId]
"render": function (data, type, row) {
return "<a href='#Url.Action("ServerMethod", "Controller")?someParam=" + row["DataElement1"] + "'>Details</a>"
},
"searchable": false,
"sortable": false
}
]
});
Here's a snippet of my server side code that returns the json collection.
tableRows is a collection of models containing the data to be displayed.
var json = this.Json(new { data = tableRows });
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return json;
As I said before, the ajax call returned data but wouldn't display until I gave the collection a name. Maybe I missed this required step in the documentation, but wouldn't it make sense for the control to wire up to a single returned collection as the default data source and not require the name? Figuring out the name thing equated to about 2+ hours of messin' around trying different things. That's all I'm saying.
Maybe this'll help someone else too...
dataTables does actually have a dataSrc property! dataTables will look for either a data or an aaData section in the JSON. Thats why you finally got it to work with new { data=tableRows }. That is, if dataSrc is not specified! If your JSON differs from that concept you must specify dataSrc :
If you return a not named array / collection [{...},{...}] :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: ""
}
If you return a JSON array named different from data or aaData, like customers :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: "customers"
}
If the content is nested like { a : { b : [{...},{...}] }}
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: "a.b"
}
If you have really complex JSON or need to manipulate the JSON in any way, like cherry picking from the content - dataSrc can also be a function :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: function(json) {
//do what ever you want
//return an array containing JSON / object literals
}
}
Hope the above clears things up!

dataTables make <tr> clickable to link

I have a dataTables table at http://communitychessclub.com/test.php
My problem is I need to make an entire table row clickable to a link based on a game#. The table lists games and user should click on a row and the actual game loads.
I am unable to understand the previous solutions to this problem. Can somebody please explain this in simple terms?
I previously did this at http://communitychessclub.com/games.php (but that version is too verbose and does disk writes with php echo)
with
echo "<tr onclick=\"location.href='basic.php?game=$game'\" >";
<script>$(document).ready(function() {
$('#cccr').dataTable( {
"ajax": "cccr.json",
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
}
],
"columns": [
{ "data": "game" },
{ "data": "date" },
{ "data": "event" },
{ "data": "eco" },
{ "data": "white_rating" },
{ "data": "white" },
{ "data": "black_rating" },
{ "data": "black" }
]
} );
} );</script>
"cccr.json" looks like this and is fine:
{
"data": [
{
"game": "5086",
"date": "09/02/2013",
"event": "135th NYS Ch.",
"eco": "B08",
"white": "Jones, Robert",
"white_rating": "2393",
"black": "Spade, Sam",
"black_rating": "2268"
},
...
You can do it this way:
Use fnRowCallback to add a game-id data-attribute to your datatable rows
...
{ "data": "black" }
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
//var id = aData[0];
var id = aData.game;
$(nRow).attr("data-game-id", id);
return nRow;
}
This will give each row in your table a game id attribute e.g:
<tr class="odd" data-game-id="5086">
Then create a javascript listener for the click event and redirect to the game page passing the game id taken from the tr data-attribute:
$('#cccr tbody').on('click', 'tr', function () {
var id = $(this).data("game-id");
window.location = 'basic.php?game=' + id;
}