Add json data to datatables - javascript

I am trying to populate datatables with a complex json scheme, however I don't know exactly how to do it.
First, some parts of json are nested and it needs iteration.
Second I need to create some markup, basically a href link.
Here is what I have:
$(document).ready(function(){
$('#empTable').DataTable({
'processing': true,
'serverSide': true,
'serverMethod': 'post',
'ajax': {
'url':'/dashboard/ajaxgetrequests',
dataSrc: "json_list"
},
'columns': [
{ data: 'firstname' },
{ data: 'funding_project_name' } // this must be a link like <a href='/<relation_id>'><funding_project_name></a>
]
});
});
{
"json_list":{
"125":{
"firstname":"John",
"funding_project_name":"A",
"relation_id": "7"
},
"133":{
"firstname":"Cesar",
"funding_project_name":[
"A",
"B"
],
"relation_id":[
"7",
"9"
]
}
}
}

1) For nested JSON you can use something like this:
// JSON structure for each row:
// {
// "engine": {value},
// "browser": {value},
// "platform": {
// "inner": {value}
// },
// "details": [
// {value}, {value}
// ]
// }
$('#example').dataTable( {
"ajaxSource": "sources/deep.txt",
"columns": [
{ "data": "engine" },
{ "data": "browser" },
{ "data": "platform.inner" },
{ "data": "details.0" },
{ "data": "details.1" }
]
} );
2) To edit and insert a link you can use columns.render (documentation)
$('#example').dataTable( {
"columnDefs": [ {
"targets": 0,
"data": "download_link",
"render": function ( data, type, row, meta ) {
return 'Download';
}
} ]
} );

Honestly, there may be a better built in way of handling this but when I experience things that do not fit the exact mold of using the base datatable functionality, I prefer to take manual control of the generation. This will give you an overview on how to do it with your structure:
Just basic html for your table (nothing really to see here):
<table id="empTable">
<thead>
<tr><th>First Name</th><th>ProjectName</th></tr>
</thead>
<tbody></tbody>
</table>
In JS we declare a variable we can use throughout our script then on ready event we instatiate our datatable:
var dt;
$(document).ready(function () {
dt = $('#empTable').DataTable();
loadDT();
});
We will also use a function call 'loadDT()' and what this will do is trigger a ajax call to the backend to get your json, in this example, I'm just gonna mock it but in your world so this on the ajax success:
Iterate your list and determine the types then use the api call row.add to dynamically add new rows to your table. (notice we are reusing the stored variable dt that we initially declared.) This is where you can do whatever custom logic fun you need to do.
function loadDT(){
var mockJSON = { "json_list":{ "125":{ "firstname":"John","funding_project_name":"A","relation_id": "7"},"133":{ "firstname":"Cesar","funding_project_name":["A","B"],"relation_id":["7","9"]}}};
$.each(mockJSON.json_list, function (i, n){
if(Array.isArray(n.funding_project_name)) {
$.each(n.funding_project_name, function (i2, p){
dt.row.add([n.firstname,'' + p + '']);
dt.draw(false);
});
} else {
dt.row.add([n.firstname, '' + n.funding_project_name + '']);
dt.draw(false);
}
});
}
Like previously stated, there may be some built in functions to handle this that I am unaware but when things get complicated, just know you can take manual control of it.
Full Example:
var dt;
$(document).ready(function () {
dt = $('#empTable').DataTable();
loadDT();
});
function loadDT(){
var mockJSON = { "json_list":{ "125":{ "firstname":"John","funding_project_name":"A","relation_id": "7"},"133":{ "firstname":"Cesar","funding_project_name":["A","B"],"relation_id":["7","9"]}}};
$.each(mockJSON.json_list, function (i, n){
var projLinks = "";
if(Array.isArray(n.funding_project_name)) {
$.each(n.funding_project_name, function (i2, p){
projLinks += '' + p + ' ';
});
} else {
projLinks = '' + n.funding_project_name + '';
}
dt.row.add([n.firstname, projLinks]);
dt.draw(false);
});
}
<link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<table id="empTable">
<thead>
<tr><th>First Name</th><th>ProjectName</th></tr>
</thead>
<tbody></tbody>
</table>

Related

row().child().show() isnt picked up by jquery datatables

After following the examples in https://datatables.net/reference/api/row().child(), I got this working in one project. Now im working on a new one, and everything was fine until the .show() came up with the error 'Property 'show()' does not exist on type Api' I followed the example and my imports seem to be up to date (this function has been in datatables since 1.10) so I dont know what could be wrong. This is in a typescript file, but as far as im aware everything still works like javascript. The function doesnt get upset if I do row.child().show(), but when I put the format function in it doesnt like that. Im still new to programming, so any help is super welcome :)
My HTML Table:
<table id="duckTable" class="display" cellspacing="0" width="80%">
<thead>
<tr>
<th>Select</th>
<th>Id</th>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
</table>
My JS table:
var duckTable = $('#duckTable').DataTable({
"ajax": {
"url": "/Ducks/getDucks",
"type": "GET",
"dataSrc":""
},
paging: false,
ordering: false,
info: false,
"columns": [
{
className: 'dropdown',
orderable: false,
data: null,
defaultContent: '',
},
{ "data": "id" },
{ "data": "name" },
{ "data": "type" }
],
order: [[1, 'asc']],
"columnDefs": [
{
"render": function (data, type, row) {
var status = row.status;
var editButton = "<i name=" + row.id + " class=\"open-table\" style=\"padding-left:27px; padding-top:10px;\">&#8595</i> ";
if (status == null || status === 'D') {
return editButton;
} else {
return "";
}
},
"targets": 0
},
{"width": "10%", "targets":0},
]
});
My function:
function format(d) {
return ('<div>Still doesnt work</div>');
}
$('#duckTable tbody').on('click', 'td.dropdown', function () {
var tr = $(this).closest('tr');
var row = duckTable.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row (the format() function would return the data to be shown)
row.child(format(row.data())).show();//this throws the error
tr.addClass('shown');
}
});
You mentioned that you're using TypeScript - the error that you're receiving sounds like a TypeScript compilation error.
This is because by the Typescript API definition that DataTables publishes, calling row.child(data) returns a union type of RowChildMethods<T> | Api<T>. Because the .show() method is not defined on the Api type, the Typescript compiler throws an error.
You should be able to get around this by splitting up your code into two statements:
row.child(format(row.data()));
row.show();

How to get parameter from another datatable column?

My objective is to carry multiple parameters in same row but from different column. In my case, each row contain of 7 columns. but only 3 parameters that I need to pass to btnApprove1 function. This function will appoint to other API which require all that 3 parameters.
So how to carry service_id, project_id and staff_id into btnApprove function when clicked?
columns: [
{ data : "service_id", "className": "text-center" },
{ data : "project_id", "className": "text-center" },
{ data : "staff_id", "className": "text-center" },
{ data : "status", "className": "text-center",
render: function(data){
if (data == "1001") {
return "<span onclick='btnApprove(""+data+"")'</span>";
}
else {
return data;
}
}
},
{ data : "lorry", "className": "text-center" },
{ data : "car", "className": "text-center" },
{ data : "van", "className": "text-center" }
]
function btnApprove(service_id, project_id, staff_id){
console.log(service_id, project_id, staff_id)
var params = {
"service_id": service_id,
"project_id": project_id,
"staff_id": staff_id
};
params = JSON.stringify(params);
$.ajax ({
...
});
}
According to the jQuery Datatable documentation for the column cell render() function, it takes four parameters, the third parameter is called row, and it's an array of values each representing the value of the column with the respective index. You can use this parameter to pass the right values to your btnApprove function.
In the code block below, I make use of destructuring on the row array to only get the first three values you need. Template literals also help make string HTML more readable.
render: function(data, type, [service_id, project_id, staff_id]) {
if (data === '1001') {
return `
<span onclick="btnApprove('${service_id}', '${project_id}', '${staff_id}')">
${data}
</span>
`;
}
return data;
}
To make sure that your <span> click event has access to btnApprove when used as a string like you have, it needs to be declared globally, on thing you can do is to change the definition of the function from:
function btnApprove(service_id, project_id, staff_id) {
To:
btnApprove = function(service_id, project_id, staff_id) {
I just solve this issue by applying this.
{ data : "status", "className": "text-center",
fnCreatedCell: function (nTd, sData, oData, iRow, iCol) {
if (oData.status == "1001") {
var stat = '<span class="badge badge-warning font-11">Approval</span><br/>';
$(nTd).html("<span onclick='btnApprove(""+oData.service_id+"", ""+oData.project_id+"", ""+oData.staff_id+"")'>"+stat+"</span>");
}
else if (oData.status == "1000") {
var stat2 = '<span class="badge badge-primary font-11">Registered</span>';
$(nTd).html("<span onclick='btnNotApprove(""+oData.service_id+"", ""+oData.project_id+"", ""+oData.staff_id+"")'>"+stat2+"</span>");
}
}
},

Geting all the selected nodes in jstree on check event?

I'm using get_bottom_selected to get all the checked/selected nodes in JSTree. When I setup a button in my form that calls the following method it works. When I try to call the same function from check box click event it does not find any selected nodes, even if there are some.
function testit() {
var data = $('#my_tree').jstree(true).get_bottom_selected(true);
for(var count = 0; count < data.length; count++){
// Do Stuff
}
}
When the following event fires I want to call the function and get all the selected child nodes, but it does not work. Is there something specific to do on this event that works different than calling from a button click event?
.on("check_node.jstree uncheck_node.jstree", function(e, data) {
testit(); // first line of this function does not get any selected data, even if several are selected. When called from a button click event in my form it does work.
});
Here's how I currently have my jstree setup.
$('#my_tree')
.on("changed.jstree", function (e, data) {
// Do Stuff
})
.jstree({
checkbox: {
"keep_selected_style": false,
"visible" : true,
"three_state": true,
"whole_node" : true,
},
plugins: ['checkbox'],
'core' : {
'multiple' : true,
'data' : {
"url" : "/static/content_data.json",
"dataType" : "json"
}
}
})
.on("check_node.jstree uncheck_node.jstree", function(e, data) {
testit();
});
Because of the strict mode you will get the exception that if you try to use get_bottom_checked
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them.
at Function.invokeGetter (<anonymous>:2:14)
You can use data.selected from your check or uncheck event handler if you just want the ids of selected nodes but if you need more than that you can use 'data.instance._model.data'. As you can see in my example I am trying to alert if there is only one item selected and that's state is open. In the code example, you can see the Alert if you open the `Europe1 and select the checkbox.
var data1 = [{
"id": "W",
"text": "World",
"state": {
"opened": true
},
"children": [{
"text": "Asia"
},
{
"text": "Africa"
},
{
"text": "Europe",
"state": {
"opened": false
},
"children": ["France", "Germany", "UK"]
}
]
}];
function testit(data) {
alert(data.length + ' and ids are ' +data );
for (var count = 0; count < data.length; count++) {
}
}
$('#Tree').jstree({
core: {
data: data1,
check_callback: false
},
checkbox: {
three_state: false, // to avoid that fact that checking a node also check others
whole_node: false, // to avoid checking the box just clicking the node
tie_selection: false // for checking without selecting and selecting without checking
},
plugins: ['checkbox']
})
$('#Tree').on("check_node.jstree uncheck_node.jstree", function(e, data) {
if (data.selected.length === 1) { alert(data.instance._model.data[data.selected].state['opened']); }
testit(data.selected);
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" type="text/css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<div id="Tree"></div>
According to this
you can get all selected nodes on change event like this:
$('#jstree').on('changed.jstree', function (e, data) {
var i, j, r = [];
for(i = 0, j = data.selected.length; i < j; i++) {
r.push(data.instance.get_node(data.selected[i]).text);
}
$('#event_result').html('Selected: ' + r.join(', '));
}).jstree();

JSON to HTML5 table

How to populate a HTML5 table if you receive data in JSON format in jQuery Ajax and based on a specific column on a row color that row on a table (Using bootstrap 4 CSS styles?)
For example if i receive a dataset in JSON format like this:
{ "name":"John", "age":31, "city":"New York" };
The column city is New York so the table row should be colored green so the finished product should be like this:
<tr class="success">
<td>John</td>
<td>31</td>
<td>New York</td>
</tr>
I'm fairly new at jQuery can anyone guide me through how this can be achieved?
I'm using datatables library at the moment and what i have done is this:
function btnSearch_Click() {
$.ajax({
type: "POST",
url: "index.aspx/GetJobs",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
$('.table-sortable').dataTable({
destroy: true,
data: data,
columns: [
{
'd': 'Name'
},
{
'd': 'Age'
},
{
'd': 'City'
}]
});
}
});
};
Current HTML5 code is displayed bellow
<table class="table table-hover thead-inverse table-bordered table-sortable">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
</table>
But when I click the button no data rows are returned by the browser (SQL Server does return data). Also as i mentioned i do not know how to accomplish that if specific data is returned in a row i need to color it...
Thank you for your help in advance...
Try this :
$('.table-sortable').dataTable({
destroy: true,
data: data,
columns: [
{ "data": "name" },
{ "data": "age" },
{ "data": "city" },
]
});
For using DataTables with ajax you usually have something like this:
$(document).ready(function () {
$('.table-sortable').dataTable({
"ajax": {
"url": "index.aspx/GetJobs",
"type": "POST"
},
"columns": [
{ "data": "name" },
{ "data": "age" },
{ "data": "city" },
]
});
});
As you can see the plugin itself has the functionality to use ajax.
So by default your returned data from server should contain a property data which contains the elements that are about to be rendered. You can actually specifiy this by using the dataSrc (reference) prop of ajax, you can set it to other name or remove it if you use plain collection:
"ajax": {
"url": "index.aspx/GetJobs",
"type": "POST"
"dataSrc": ""
},
This however does not change the data name in columns declaration so don't change it there.
You can read more about accepted formats and see examples in the official documentation.
Now regarding your question about row styling, there are a lot of callbacks and declarations which you can use to achieve that. I personally prefer using the createdRow callback (reference):
"createdRow": function( row, data, dataIndex ) {
if ( parseInt(data[1]) >= 18 ) {
$(row).addClass( 'success' );
}
}
So in this case if the age (second column based on 0-start-indexing) of the current row is above 18 it will add the desired class.
I hope this helps resolving your issues, if there still are problems you can try making a working jsfiddle so we can try debugging it in a "real-like" situation.
This is just to get an idea, i will add button click code
$("button").click(function(){
var obj = JSON.parse('[{ "name":"John", "age":30, "city":"New York"},{ "name":"John1", "age":30, "city":"New York"}]');
var t = $('#example');
for (i = 0; i < obj.length; i++) // iterate data from json
{
var name = obj[i].name;
var age = obj[i].age;
var classStyle = 'yellow'
if(name=='John')
{
classStyle = 'green';
}
$('#example').append('<tr style=background:'+classStyle+'><td>'+name+'</td><td>'+age+'</td></tr>');
}
});

FuelUX datagrid not loading (using example)

I'm new to FuelUX so I was trying to get this to work, based on the example provided:
require(['jquery','data.js', 'datasource.js', 'fuelux/all'], function ($, sampleData, StaticDataSource) {
var dataSource = new StaticDataSource({
columns: [{property:"memberid",label:"LidId",sortable:true},{property:"name",label:"Naam",sortable:true},{property:"age",label:"Leeftijd",sortable:true}],
data: sampleData.memberdata,
delay: 250
});
$('#MyGrid').datagrid({
dataSource: dataSource,
stretchHeight: true
});
});
});
With this as the data:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else {
root.sampleData = factory();
}
}(this, function () {
return {
"memberdata": [{
"memberid": 103,
"name": "Laurens Natzijl",
"age": "25"
}, {
"memberid": 104,
"name": "Sandra Snoek",
"age": "25"
}, {
"memberid": 105,
"name": "Jacob Kort",
"age": "25"
}, {
"memberid": 106,
"name": "Erik Blokker",
"age": "25"
}, {
"memberid": 107,
"name": "Jacco Ruigewaard",
"age":"25"
},{ /* etc */ }]
}
}));
I've got no console errors, no missing includes. Everthing works just fine - it even looks like it's loading. Except nothing shows up in the datagrid but '0 items'.
Any suggestions? I think I did everything the example provided...
EDIT: 14:33 (Amsterdam)
There seems to be a difference when I put this in console:
My page:
require(['jquery','data.js','datasource.js', 'fuelux/all'], function ($, sampleData, StaticDataSource) {
var dataSource = new StaticDataSource({
columns: [{property:"memberid",label:"LidId",sortable:true},{property:"name",label:"Naam",sortable:true},{property:"age",label:"Leeftijd",sortable:true}],
data: sampleData.memberdata,
delay: 250
});
console.debug(dataSource);
});
1st row in console:
function localRequire(deps, callback, errback) { /* etc */ }
2nd row in console:
StaticDataSource {_formatter: undefined, _columns: Array[3], _delay: 250, _data: Array[25], columns: function…}
FuelUX Example:
require(['jquery', 'sample/data', 'sample/datasource', 'sample/datasourceTree', 'fuelux/all'], function ($, sampleData, StaticDataSource, DataSourceTree) {
var dataSource = new StaticDataSource({
columns: [{property: 'toponymName',label: 'Name',sortable: true}, {property: 'countrycode',label: 'Country',sortable: true}, {property: 'population',label: 'Population',sortable: true}, {property: 'fcodeName',label: 'Type',sortable: true}],
data: sampleData.geonames,
delay: 250
});
console.debug(dataSource);
});
1st row in console:
StaticDataSource {_formatter: undefined, _columns: Array[4], _delay: 250, _data: Array[146], columns: function…}
2nd row in console:
function (deps, callback, errback, relMap) { /* etc */ }
Maybe this will help you help me :)
I didn't see all of the information I needed to provide a finite answer. The real magic is the datasource.js file (which you had not provided).
I thought an easier way of demonstrating all the necessary pieces would be to put together a JSFiddle showing your data in use and all the pieces that were necessary.
Link to JSFiddle of Fuel UX Datagrid sample with your data
Adam Alexander, the author of the tool, also has written a valuable example of using the dataGrid DailyJS Fuel UX DataGrid
// DataSource Constructor
var StaticDataSource = function( options ) {
this._columns = options.columns;
this._formatter = options.formatter;
this._data = options.data;
this._delay = options.delay;
};
StaticDataSource.prototype = {
columns: function() {
return this._columns
},
data: function( options, callback ) {
var self = this;
var data = $.extend(true, [], self._data);
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
for (var prop in item) {
if (!item.hasOwnProperty(prop)) continue;
if (~item[prop].toString().toLowerCase().indexOf(options.search.toLowerCase())) return true;
}
return false;
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: 0, end: 0, count: 0, pages: 0, page: 0 });
}
};
If you were to provide your markup and what your "datasource.js" file contains, I may be able to help you further.
I think the demonstration provides much information on any pieces you may not have understood.
Adding on to creatovisguru's answer:
In his JSFiddle example, pagination is broken. To fix it, change the following line:
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
I had the exact same issue, when tried to integrate with Django. The issue I believe is on this line :
require(['jquery','data.js','datasource.js', 'fuelux/all'], function ($, sampleData, StaticDataSource) {
I was not able to specify file extension, my IDE (pycharm), would mark "red", when used "data.js", so it needs to stay without an extension, such as "sample/data"
What I end up doing to make it work, is downloading the full fuelux directory from github in /var/www/html on a plain Apache setup ( no django, to avoid URL.py issues for static files ) and everything works using their example. Here are the steps to get you started :
cd /var/www/html
git clone https://github.com/ExactTarget/fuelux.git
and you will end up with fuelux in /var/www/html/fuelux/
in your browser, navigate to : http://foo.com/fuelux/index.html ( assuming your default document root is /var/www/html )
good luck!

Categories