Convert JSON array to an HTML table in jQuery - javascript

Is there a really easy way I can take an array of JSON objects and turn it into an HTML table, excluding a few fields? Or am I going to have to do this manually?

Using jQuery will make this simpler.
The following code will take an array of arrays and store convert them into rows and cells.
$.getJSON(url , function(data) {
var tbl_body = "";
var odd_even = false;
$.each(data, function() {
var tbl_row = "";
$.each(this, function(k , v) {
tbl_row += "<td>"+v+"</td>";
});
tbl_body += "<tr class=\""+( odd_even ? "odd" : "even")+"\">"+tbl_row+"</tr>";
odd_even = !odd_even;
});
$("#target_table_id tbody").html(tbl_body);
});
You could add a check for the keys you want to exclude by adding something like
var expected_keys = { key_1 : true, key_2 : true, key_3 : false, key_4 : true };
at the start of the getJSON callback function and adding:
if ( ( k in expected_keys ) && expected_keys[k] ) {
...
}
around the tbl_row += line.
Edit: Was assigning a null variable previously
Edit: Version based on Timmmm's injection-free contribution.
$.getJSON(url , function(data) {
var tbl_body = document.createElement("tbody");
var odd_even = false;
$.each(data, function() {
var tbl_row = tbl_body.insertRow();
tbl_row.className = odd_even ? "odd" : "even";
$.each(this, function(k , v) {
var cell = tbl_row.insertCell();
cell.appendChild(document.createTextNode(v.toString()));
});
odd_even = !odd_even;
});
$("#target_table_id").append(tbl_body); //DOM table doesn't have .appendChild
});

I'm not sure if is this that you want but there is jqGrid. It can receive JSON and make a grid.

Make a HTML Table from a JSON array of Objects by extending $ as shown below
$.makeTable = function (mydata) {
var table = $('<table border=1>');
var tblHeader = "<tr>";
for (var k in mydata[0]) tblHeader += "<th>" + k + "</th>";
tblHeader += "</tr>";
$(tblHeader).appendTo(table);
$.each(mydata, function (index, value) {
var TableRow = "<tr>";
$.each(value, function (key, val) {
TableRow += "<td>" + val + "</td>";
});
TableRow += "</tr>";
$(table).append(TableRow);
});
return ($(table));
};
and use as follows:
var mydata = eval(jdata);
var table = $.makeTable(mydata);
$(table).appendTo("#TableCont");
where TableCont is some div

Pure HTML way, not vulnerable like the others AFAIK:
// Function to create a table as a child of el.
// data must be an array of arrays (outer array is rows).
function tableCreate(el, data)
{
var tbl = document.createElement("table");
tbl.style.width = "70%";
for (var i = 0; i < data.length; ++i)
{
var tr = tbl.insertRow();
for(var j = 0; j < data[i].length; ++j)
{
var td = tr.insertCell();
td.appendChild(document.createTextNode(data[i][j].toString()));
}
}
el.appendChild(tbl);
}
Example usage:
$.post("/whatever", { somedata: "test" }, null, "json")
.done(function(data) {
rows = [];
for (var i = 0; i < data.Results.length; ++i)
{
cells = [];
cells.push(data.Results[i].A);
cells.push(data.Results[i].B);
rows.push(cells);
}
tableCreate($("#results")[0], rows);
});

Converting a 2D JavaScript array to an HTML table
To turn a 2D JavaScript array into an HTML table, you really need but a little bit of code :
function arrayToTable(tableData) {
var table = $('<table></table>');
$(tableData).each(function (i, rowData) {
var row = $('<tr></tr>');
$(rowData).each(function (j, cellData) {
row.append($('<td>'+cellData+'</td>'));
});
table.append(row);
});
return table;
}
$('body').append(arrayToTable([
["John","Slegers",34],
["Tom","Stevens",25],
["An","Davies",28],
["Miet","Hansen",42],
["Eli","Morris",18]
]));
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
Loading a JSON file
If you want to load your 2D array from a JSON file, you'll also need a little bit of Ajax code :
$.ajax({
type: "GET",
url: "data.json",
dataType: 'json',
success: function (data) {
$('body').append(arrayToTable(data));
}
});

For very advanced JSON objects to HTML tables you can try My jQuery Solution that is based on this closed thread.
var myList=[{"name": "abc","age": 50},{"name": {"1": "piet","2": "jan","3": "klaas"},"age": "25","hobby": "watching tv"},{"name": "xyz","hobby": "programming","subtable": [{"a": "a","b": "b"},{"a": "a","b": "b"}]}];
// Builds the HTML Table out of myList json data from Ivy restful service.
function buildHtmlTable() {
addTable(myList, $("#excelDataTable"));
}
function addTable(list, appendObj) {
var columns = addAllColumnHeaders(list, appendObj);
for (var i = 0; i < list.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = list[i][columns[colIndex]];
if (cellValue == null) {
cellValue = "";
}
if (cellValue.constructor === Array)
{
$a = $('<td/>');
row$.append($a);
addTable(cellValue, $a);
} else if (cellValue.constructor === Object)
{
var array = $.map(cellValue, function (value, index) {
return [value];
});
$a = $('<td/>');
row$.append($a);
addObject(array, $a);
} else {
row$.append($('<td/>').html(cellValue));
}
}
appendObj.append(row$);
}
}
function addObject(list, appendObj) {
for (var i = 0; i < list.length; i++) {
var row$ = $('<tr/>');
var cellValue = list[i];
if (cellValue == null) {
cellValue = "";
}
if (cellValue.constructor === Array)
{
$a = $('<td/>');
row$.append($a);
addTable(cellValue, $a);
} else if (cellValue.constructor === Object)
{
var array = $.map(cellValue, function (value, index) {
return [value];
});
$a = $('<td/>');
row$.append($a);
addObject(array, $a);
} else {
row$.append($('<td/>').html(cellValue));
}
appendObj.append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records
function addAllColumnHeaders(list, appendObj)
{
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < list.length; i++) {
var rowHash = list[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
appendObj.append(headerTr$);
return columnSet;
}

One simple way of doing this is:
var data = [{
"Total": 34,
"Version": "1.0.4",
"Office": "New York"
}, {
"Total": 67,
"Version": "1.1.0",
"Office": "Paris"
}];
drawTable(data);
function drawTable(data) {
// Get Table headers and print
var head = $("<tr />")
$("#DataTable").append(head);
for (var j = 0; j < Object.keys(data[0]).length; j++) {
head.append($("<th>" + Object.keys(data[0])[j] + "</th>"));
}
// Print the content of rows in DataTable
for (var i = 0; i < data.length; i++) {
drawRow(data[i]);
}
}
function drawRow(rowData) {
var row = $("<tr />")
$("#DataTable").append(row);
row.append($("<td>" + rowData["Total"] + "</td>"));
row.append($("<td>" + rowData["Version"] + "</td>"));
row.append($("<td>" + rowData["Office"] + "</td>"));
}
table {
border: 1px solid #666;
width: 100%;
text-align: center;
}
th {
background: #f8f8f8;
font-weight: bold;
padding: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="DataTable"></table>

You could use a jQuery plugin that accepts JSON data to fill a table.
jsonTable

I found a duplicate over here: Convert json data to a html table
Well, there are many plugins exists, including commercial one (Make this as commercial project?! Kinda overdone... but you can checkout over here: https://github.com/alfajango/jquery-dynatable)
This one has more fork: https://github.com/afshinm/Json-to-HTML-Table
//Example data, Object
var objectArray = [{
"Total": "34",
"Version": "1.0.4",
"Office": "New York"
}, {
"Total": "67",
"Version": "1.1.0",
"Office": "Paris"
}];
//Example data, Array
var stringArray = ["New York", "Berlin", "Paris", "Marrakech", "Moscow"];
//Example data, nested Object. This data will create nested table also.
var nestedTable = [{
key1: "val1",
key2: "val2",
key3: {
tableId: "tblIdNested1",
tableClassName: "clsNested",
linkText: "Download",
data: [{
subkey1: "subval1",
subkey2: "subval2",
subkey3: "subval3"
}]
}
}];
Apply the code
//Only first parameter is required
var jsonHtmlTable = ConvertJsonToTable(objectArray, 'jsonTable', null, 'Download');
Or you might want to checkout this jQuery plugins as well: https://github.com/jongha/jquery-jsontotable
I think jongha's plugins is easier to use
<div id="jsontotable" class="jsontotable"></div>
var data = [[1, 2, 3], [1, 2, 3]];
$.jsontotable(data, { id: '#jsontotable', header: false });

If you accept using another jQuery dependent tool, I would recommend using Tabulator. Then you will not need to write HTML or any other DOM generating code, while maintaining great flexibility regarding the formatting and processing of the table data.
For another working example using Node, you can look at the MMM-Tabulator demo project.

with pure jquery:
window.jQuery.ajax({
type: "POST",
url: ajaxUrl,
contentType: 'application/json',
success: function (data) {
var odd_even = false;
var response = JSON.parse(data);
var head = "<thead class='thead-inverse'><tr>";
$.each(response[0], function (k, v) {
head = head + "<th scope='row'>" + k.toString() + "</th>";
})
head = head + "</thead></tr>";
$(table).append(head);//append header
var body="<tbody><tr>";
$.each(response, function () {
body=body+"<tr>";
$.each(this, function (k, v) {
body=body +"<td>"+v.toString()+"</td>";
})
body=body+"</tr>";
})
body=body +"</tbody>";
$(table).append(body);//append body
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responsetext);
}
});

You can do this pretty easily with Javascript+Jquery as below.
If you want to exclude some column, just write an if statement inside the for loops to skip those columns. Hope this helps!
//Sample JSON 2D array
var json = [{
"Total": "34",
"Version": "1.0.4",
"Office": "New York"
}, {
"Total": "67",
"Version": "1.1.0",
"Office": "Paris"
}];
// Get Table headers and print
for (var k = 0; k < Object.keys(json[0]).length; k++) {
$('#table_head').append('<td>' + Object.keys(json[0])[k] + '</td>');
}
// Get table body and print
for (var i = 0; i < Object.keys(json).length; i++) {
$('#table_content').append('<tr>');
for (var j = 0; j < Object.keys(json[0]).length; j++) {
$('#table_content').append('<td>' + json[i][Object.keys(json[0])[j]] + '</td>');
}
$('#table_content').append('</tr>');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr id="table_head">
</tr>
</thead>
<tbody id="table_content">
</tbody>
</table>

Modified a bit code of #Dr.sai 's code. Hope this will be useful.
(function ($) {
/**
* data - array of record
* hidecolumns, array of fields to hide
* usage : $("selector").generateTable(json, ['field1', 'field5']);
*/
'use strict';
$.fn.generateTable = function (data, hidecolumns) {
if ($.isArray(data) === false) {
console.log('Invalid Data');
return;
}
var container = $(this),
table = $('<table>'),
tableHead = $('<thead>'),
tableBody = $('<tbody>'),
tblHeaderRow = $('<tr>');
$.each(data, function (index, value) {
var tableRow = $('<tr>').addClass(index%2 === 0 ? 'even' : 'odd');
$.each(value, function (key, val) {
if (index == 0 && $.inArray(key, hidecolumns) <= -1 ) {
var theaddata = $('<th>').text(key);
tblHeaderRow.append(theaddata);
}
if ($.inArray(key, hidecolumns) <= -1 ) {
var tbodydata = $('<td>').text(val);
tableRow.append(tbodydata);
}
});
$(tableBody).append(tableRow);
});
$(tblHeaderRow).appendTo(tableHead);
tableHead.appendTo(table);
tableBody.appendTo(table);
$(this).append(table);
return this;
};
})(jQuery);
Hoping this will be helpful to hide some columns too.
Link to file

Pivoted single-row view with headers on the left based on #Dr.sai's answer above.
Injection prevented by jQuery's .text method
$.makeTable = function (mydata) {
var table = $('<table>');
$.each(mydata, function (index, value) {
// console.log('index '+index+' value '+value);
$(table).append($('<tr>'));
$(table).append($('<th>').text(index));
$(table).append($('<td>').text(value));
});
return ($(table));
};

Make a HTML Table from a JSON array of Objects by extending $ as shown below
$.makeTable = function (mydata, cssClass) {
if (!cssClass) cssClass = "table table-bordered table-stripped table-dark"
var table = $('<table class="' + cssClass + '">');
var tblHeader = "<thead><tr>";
for (var k in mydata[0]) tblHeader += "<th>" + k + "</th>";
tblHeader += "</tr></thead>";
$(tblHeader).appendTo(table);
var TableRow = "<tbody>";
$.each(mydata, function (index, value) {
TableRow += "<tr id=_ID_>".replace("_ID_", value.name);
$.each(value, function (key, val) {
TableRow += "<td>" + val + "</td>";
});
TableRow += "</tr>";
});
TableRow += "</tbody>";
$(table).append(TableRow);
return ($(table));
};
Usage as Below
var EmployeeArr = [];
for (let i = 0; i < 100; ++i) {
let emp = {};
emp.name = "Varsha_" + i;
emp.age = Math.round((Math.random() * 100 + 10)) * 3
EmployeeArr.push(emp);
}
var table = $.makeTable(EmployeeArr );
$(table).appendTo("#TableCont");
where TableCont is some div

A still shorter way
$.makeTable = function (mydata) {
if (mydata.length <= 0) return "";
return $('<table border=1>').append("<tr>" + $.map(mydata[0], function (val, key) {
return "<th>" + key + "</th>";
}).join("\n") + "</tr>").append($.map(mydata, function (index, value) {
return "<tr>" + $.map(index, function (val, key) {
return "<td>" + val + "</td>";
}).join("\n") + "</tr>";
}).join("\n"));
};

Related

How do I get object data from my json in my select?

So I have a select element and I am appending the data I am getting back from my API.
function getHeadData() {
$("#itemSelect").empty();
if (headitemData.length < 1) {
$.getJSON("http://localhost:9000/api/helmets", function (key, value) {
console.log("request helmets");
var item = "";
headitemData = key;
var len = key.length;
for (let i = 0; i < len; i++) {
item += '<option value="' + key + '">' + key[i].Name + '</option>';
}
$('#itemSelect').append(item);
});
}
else {
clearIndex(headitemData);
}
}
That right there returns this
Which is just what I want.
But if I want to get other data like.. the Icon
Let's say I want to log to the console when I select a item from the Select element, how would I do that?
The end goal is to print out the Icon property of the json object when I change item in the Select.
JsonData example
<ItemModel>
<ACrush>+0</ACrush>
<AMagic>-5</AMagic>
<ARange>-2</ARange>
<ASlash>+0</ASlash>
<AStab>+0</AStab>
<DCrush>+43</DCrush>
<DMagic>-3</DMagic>
<DRange>+48</DRange>
<DSlash>+49</DSlash>
<DStab>+47</DStab>
<Icon>
https://vignette.wikia.nocookie.net/2007scape/images/a/a0/3rd_age_full_helmet.png/revision/latest?cb=20141217224936
</Icon>
<MagicDamage>+0%</MagicDamage>
<MeleeStrength>+0</MeleeStrength>
<Name>3rd age full helmet</Name>
<Prayer>+0</Prayer>
<RangedStrength>+0</RangedStrength>
<Slayer>0</Slayer>
<Undead>0</Undead>
</ItemModel>
You can set a data for your option like:
'<option data-icon="'+ key[i].Icon +'"></option>'
And then you can bind a change for your select after create your list:
$('select').on('change', function () {
const _this = $(this).find(':selected');
const icon = _this.attr('data-icon');
console.log(icon);
})
Since you want to use the data in other areas of your code, use a closure to create an environment where your variables don't leak out into the global space. For example, with the callback:
(function () {
var myData;
function test(callback) {
$.getJSON("http://localhost:9000/api/helmets",function (data) {
callback(data);
});
}
test(function (data) {
myData = data;
});
function getHeadData() {
$("#itemSelect").empty();
if (headitemData.length < 1){
console.log("request helmets");
var item = "";
headitemData = myData;
var len = myData.length;
for (let i = 0; i < len; i++) {
item += '<option value="' +myData+ '">' + myData[i].Name + '</option>';
}
$('#itemSelect').append(item);
}
else {
clearIndex(headitemData);
}
}
$("#itemSelect").on("change",function(){
var value = $(this).val();
var newData = myData.filter(item=>{
if(myData.Name==value){
return item;
}
});
console.log(newData.Icon);
});
myData is cached as a global variable specific to that closure. Note the other functions will only be able to use that variable once the callback has completed.
Modified version below:
function getHeadData() {
$("#itemSelect").empty();
if (headitemData.length < 1) {
$.getJSON("http://localhost:9000/api/helmets", function (key, value) {
console.log("request helmets");
var item = "";
headitemData = key;
var len = key.length;
for (let i = 0; i < len; i++) {
var icon=key[i].Icon;
item += '<option data-icon="'+icon+'" value="' + key + '">' + key[i].Name + '</option>';
}
$('#itemSelect').append(item);
});
}
else {
clearIndex(headitemData);
}
}
Simple test to get the Icon from the first option in select:
//Get first option to test output
var test=$("#itemselect option:first");
//Read data-icon
console.log(test.data('icon'));
//To update data-icon
test.data('icon','new icon');
To echo when select is changed
$("#itemselect").change(function(e) {
var optionSelected = $("option:selected", this);
console.log (optionSelected.data('icon'));
});

How to add the input data(many data) into table below within same page?

List<Object1> list = new ArrayList<>();
List<Object2> list = new ArrayList<>();
ADD LIST button is for add the code and value to the textbox as show below.
ADD button is to add the all input data into the table below.
DELETE button is for delete from table
SUBMIT button is for post to server.
So what I have trying to do is
For button Add not Add List <- No idea for this at all!
function Add() {
var url = "/root/info/add&"+$("#fieldrows").serialize();
uField(url);
return false;
}
function uField(url) {
$.ajax({
type: 'GET'
url: url,
async: false,
success: function(data) {
try {
var res = eval("("+data+")");
if (res.success) {
var content="";
$.each(res.result, function(i, f) {
content+=addRow((i%2==1),f.seq,f.name,....);
});
$("#fieldrows").find("tbody").html(content);
bindFieldLink();
} else {
alert(res.error);
}
}catch(e) {}
}
});
}
function addRow(odd, seq,name,...) {
var oddS = "odd";
if (!odd) { oddS = "even"; }
var style="";
var seq="<a id='field_id_"+seq+"' class='fLink' href='#'>"+label+"</a>";
var row = "<tr class='"+oddS+"'><td class='chk'><input type='checkbox' seq='ids' value='"+seq+"' class='checkbox'></td>";
row += "<td>"+seq+"</td>";
row += "<td>"+rexp+"</td>";
row +="</tr>";
return row;
}
Call the function to call to server via ajax, not sure what is .serialize() for url
At server it return as JSON, I am new to this also.
After that build html for result table. But I am not sure what is bindFieldLink().
Someone please help. I am using JAVA, Spring MVC. Thank you so much.
This post can be close.
var myJson = [{"name" : "abc", "age" : 50},
{"age" : "25", "hobby" : "swimming"},
{"name" : "xyz", "hobby" : "programming"}];
// Builds the HTML Table out of myList.
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0 ; i < myJson.length ; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0 ; colIndex < columns.length ; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) { cellValue = ""; }
row$.append($('<td/>').html(cellValue));
}
$(selector).append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records
function addAllColumnHeaders(myList){
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0 ; i < myList.length ; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1){
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$(selector).append(headerTr$);
return columnSet;
}​
HTML:
<body onLoad="buildHtmlTable('#excelDataTable')">
<table id="excelDataTable" border="1">
</table>
</body>​

How to loop json data in jquery or filter a certain data so that it wont repeat

I'm confuse on jquery, it's not the same on php.
I want to achieve this kind of table but the output of my jquery is this
Here is my json
Jquery:
$.get('/dev/api/getPODetails?id=' + id, function(data){
$.each(data, function(index, getPODetails){
$('.table tbody').append('<tr><td>'+getPODetails.id+'</td></tr>');
$('.table tbody').append('<tr><td>'+getPODetails.itemdesc+'</td></tr>');
})
})
});
I don't know what's the problem of the loop, all I want is to display none repeating PO#. Can someone share some idea? Thank you in advance.
Try this, i make it easier way:
Controller:
public function getPOHeader(){
$supplierid = Input::get('id');
$getPOHeader = PurchaseHeader::where('partner_id', $supplierid)
->get();
return Response::json($getPOHeader, 200, array(), JSON_PRETTY_PRINT);
}
public function getPODetails(){
$supplierid = Input::get('id');
$getPODetails = DB::table('purchase_details')
->where('purchase_details.po_no_id', $supplierid)
->leftJoin('items', 'purchase_details.item_id', '=', 'items.id')
->join('uoms', 'purchase_details.uom_id', '=', 'uoms.id')
->select('items.description as itemdesc', 'purchase_details.qty as ordered', 'uoms.name as uom',
'purchase_details.price as unitprice', 'purchase_details.disc as disc', 'purchase_details.disc_type as disc_type',
'purchase_details.total_amt as netunitprice')
->get();
return Response::json($getPODetails, 200, array(), JSON_PRETTY_PRINT);
}
My view:
$.get('/dev/api/getPOHeader?id=' + id, function(data){
$.each(data, function(index, getPOHeader){
$.get('/dev/api/getPODetails?id=' + getPOHeader.id , function(data1){
$('.table tbody').append('<tr><th><label ><strong>PO #'+getPOHeader.id+'</strong></label></th></tr>');
$.each(data1, function(index, getPODetails){
$('.table tbody').append('<tr><td><label>'+getPODetails.itemdesc+'</label></td><td><label>'+getPODetails.ordered+'</label></td><td>---------</td><td><input type="text" name="" ></td><td><label>'+getPODetails.uom+'</label></td><td><label>'+getPODetails.unitprice+'</label></td><td><label>'+getPODetails.disc+'</label></td><td><label>'+getPODetails.disc_type+'</label></td><td><label>'+getPODetails.netunitprice+'</label></td><td><label>00.00</label></td></tr>');
})
})
})
});
and the route:
Route::get('dev/api/getPOHeader','Search\SearchDataController#getPOHeader');
Route::get('dev/api/getPODetails','Search\SearchDataController#getPODetails');
You have to take a separate javascript array so that no element repeats in the loop.
$.get('/dev/api/getPODetails?id=' + id, function(data){
var dataDisplayed = [];
$.each(data, function(index, getPODetails){
if(jQuery.inArray(getPODetails.id, dataDisplayed) !== -1)
{
return;
}
$('.table tbody').append('<tr><td>'+getPODetails.id+'</td></tr>');
$('.table tbody').append('<tr><td>'+getPODetails.itemdesc+'</td></tr>');
dataDisplayed.push(getPODetails.id);
})
});
I think the above code will work for you.. :-)
You have to store a reference to the id somewhere.
$.getJSON('/dev/api/getPODetails?id=' + id, function(data){
var store = {};
for (var i = 0, len = data.length; i < len; ++i) {
if (!store[data[i].id]) = {itemdesc: data[i].itemdesc, ordered: 0}
store[data[i]].ordered += parseInt(data[i].ordered);
}
for (var key in store) {
$('.table tbody')
.append('<tr><td>' + store[key].id + '</td></tr>')
.append('<tr><td>' + store[key].itemdesc + '</td></tr>');
}
});
Or something like
$.getJSON('/dev/api/getPODetails?id=' + id, function(data){
var used = [];
for (var i = 0, len = data.length; i < len; ++i) {
if (used.indexOf(data[i].id) < 0) {
$('.table tbody')
.append('<tr><td>' + data[i].id + '</td></tr>')
.append('<tr><td>' + data[i].itemdesc + '</td></tr>');
used.push(data[i].id);
}
}
});

Generate table from Object data

I have an object like the one below:
var obj = {
a : {
x : 1,
y : 2,
z : 3
},
b : {
x : 1,
y : 2,
z : 3
}
}
With it, I will like to generate the following table. Format is showed bellow
http://jsfiddle.net/gD87t/
I am trying to get the elements from object and and trying to append but getting confused with the rowSpan value
var tr = document.createElement('tr');
for(var i in obj){
var td = document.createElement('td');
td.rowSpan = ? // Here I am getting confused.
}
Can a template engine solve my problem?
What is the best way to do this?
Here's one way of doing it with a recursive function in pure js:
function addObjectToTable(table, obj, tr) {
var rows = 0;
for (key in obj) {
if (tr == null) {
tr = document.createElement('tr');
table.appendChild(tr);
}
var td = document.createElement('td');
td.textContent = key;
tr.appendChild(td);
var value = obj[key];
if (typeof value != 'object') {
var td = document.createElement('td');
td.textContent = value;
tr.appendChild(td);
rows += 1;
}
else {
var subrows = addObjectToTable(table, value, tr);
td.setAttribute('rowspan',subrows);
rows += subrows;
}
tr = null;
}
return rows;
}
Which would be called like this:
var table = document.createElement('table');
addObjectToTable(table,obj);
document.body.appendChild(table);
Note that when first called, the tr parameter is null, since we always have to create a new row at the top level. When the function is called recursively though, the tr parameter is passed in from the upper level since lower levels will intially be adding to the the row of their parent object.
The function returns the number of rows added, so when it is called recusively the caller will know what to set the rowspan value to.
Fiddle link
I couldn't find an answer which handled circulars, and I also decided to do this without any unnecessary DOM writes. Also, I didn't follow the exact mark-up the OP requested because I felt nesting tables was more convenient for a recursive operation such as this- and serves close to the same visual purpose.
So, here's the function I've created:
function dataToTable (data) {
var storage = [];
return (function buildTable (data) {
var table = '<table><tbody>';
var name, value;
// Add the object/array to storage for cirular detection.
storage.push(data);
for (name in data) {
value = data[name];
table += '<tr><td>' + name + '</td><td>';
// If the value is an object we've put in storage (circular)
if (storage.indexOf(value) !== -1) {
table += '<em>Circular</em>';
} else if (typeof value === 'object') {
table += buildTable(value);
} else {
table += value;
}
table += '</td></tr>';
}
return table + '</tbody></table>';
}(data));
}
Here is the object I used to test:
var obj = {
a : {
x : 1,
y : 2,
z : 3
},
b : {
x : 1,
y : 2,
z : {
test1: 0,
test2: {
test3: 1,
test4: ['a','b','c']
}
}
}
};
obj.c = obj;
obj.b.z.test2.test4.push(obj.a);
The function will turn this object into an HTML table. What you do with the table is up to you. On my fiddle, I used the DOM to add the table to a DIV (document.getElementById).
http://jsfiddle.net/5RhXF/1/
I hope you'll find my implementation clear.
UPDATE::
I decided to test this on the jQuery library, and it worked! Except, the functions were printing as their toString value with no good format for text.. Which makes sense, but not very helpful. So, I'm thinking this is a nice and easy way to look through APIs for frameworks/libraries and what-not. Therefore, I added prettify for syntax-highlighting of functions, and also added a type-check for functions in the table generator, and a quick class to get rid of borders around the prettify box (as there's already a border on the table cell). If anyone is interested in the version designed for source-reading/debugging, here's the fiddle:
http://jsfiddle.net/5RhXF/7/
UPDATED: if you don't need empty cells solution could be (check fiddle http://jsfiddle.net/gD87t/11/)
Example object :
var obj = {
a : {
x : 1,
y : 2,
z : {
c : 4,
d : 5
}
},
b : {
x : 1,
y : 2,
z : 3
}
}
And routine to build table:
function merge(rows , inner) {
inner.reduce(function (i, p) {
rows.push(i)
})
}
function getRows(o) {
var rows = []
if (typeof o == 'object') {
for (var k in o) {
var innerRows = getRows(o[k])
, firstCell = $('<td />')
.text(k)
.attr('rowspan',innerRows.length)
innerRows[0].prepend(firstCell)
rows = rows.concat(innerRows)
}
} else {
var tr = $('<tr />')
, td = $('<td />').text(o)
tr.append(td)
rows.push(tr)
}
return rows
}
function buildTable(o, $t) {
var rows = getRows(o)
$t.append(rows)
}
buildTable(obj, $('#table2'))
The value for the rowspan is the number of properties in the inner object. You can use the Object.keys function to get a list of the keys on the object, then use its length property to determine how many properties there are:
for(var i in obj){
var td = document.createElement('td');
td.rowSpan = Object.keys(obj[i]).length;
}
var table = document.createElement('table');
var i, j;
var row, cell;
for(i in obj) {
if(obj.hasOwnProperty(i)) {
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.rowSpan = Object.keys(obj[i]).length;
cell.innerText = i;
row.appendChild(cell);
for(j in obj[i]) {
if(obj[i].hasOwnProperty(j)) {
cell = document.createElement('td');
cell.innerText = j;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerText = obj[i][j];
row.appendChild(cell);
table.appendChild(row);
row = document.createElement('tr');
}
}
}
}
document.body.appendChild(table);
Of course, it would look less verbose in jQuery. But it looked like you wanted to do it in plain DOM.
See it woking
well it was really tricky but I think it is done. By the way I still suggest table-less solution. you can check the working code here
var obj = {
a : {
x : 1,
y : 2,
z : {c:1, d:3}
},
b : {
x : 1,
y : 2,
z : 3
}
}
var table = document.createElement('table');
function createTable (o, parentCells) {
for (var key in o) {
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.rowSpan = 1;
cell.innerText = key;
if (typeof o[key] !== "object") {
var cellv = document.createElement('td');
cellv.innerText = o[key];
row.appendChild(cell);
row.appendChild(cellv);
table.appendChild(row);
}
else {
for (var i = 0; i < parentCells.length; i++) {
parentCells[i].rowSpan += Object.keys(o[key]).length;
}
cell.rowSpan += Object.keys(o[key]).length;
var newParentCells = new Array(parentCells);
newParentCells.push(cell);
row.appendChild(cell);
table.appendChild(row);
createTable(o[key], newParentCells);
}
}
}
createTable(obj, []);
document.body.appendChild(table);
If you wish to use document.createElement as you do in your question, the easiest way is probably like this:
function generateTable(o) {
var table, tr, td, i, j, l, keys;
table = document.createElement('table')
for(i in o){
tr = document.createElement('tr');
table.appendChild(tr);
td = document.createElement('td');
keys = Object.keys(o[i]);
td.rowSpan = keys.length;
td.textContent = i;
tr.appendChild(td);
x=0;
for(j=0;j<keys.length;j++) {
if(j) {
tr = document.createElement('tr');
table.appendChild(tr);
}
td = document.createElement('td');
td.textContent = keys[j];
tr.appendChild(td);
td = document.createElement('td');
td.textContent =o[i][keys[j]];
tr.appendChild(td);
}
}
return table;
}
CAVEAT: Object.keys isn't available in older browsers so you'll need a polyfill like this:
(taken from MOZILLA DEVELOPER NETWORK)
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
};
})();
}
Alternatively there is a much simpler polyfill that will cover most cases quite well here:
(Taken from Token Posts)
if (!Object.keys) Object.keys = function(o) {
if (o !== Object(o))
throw new TypeError('Object.keys called on a non-object');
var k=[],p;
for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p);
return k;
}
You can see a fiddle of it in action here: http://jsfiddle.net/uyJv2/

JQGrid MultiSelect getting the column data

Is there a way for the JQGrid to return an array of column Data for using multiSelect as opposed to just an array of rowIds ?
At the moment I can only return the last column data that was selected.
jQuery("#buttonSelected").click(function() {
var ids = jQuery("#relatedSearchGrid").getGridParam('selarrrow');
var count = ids.length;
for (var i = 0; i < count; i++) {
var columnData = $("#relatedSearchGrid").find("tbody")[0].rows[$("#relatedSearchGrid").getGridParam('selrow') - 1].cells[1].innerHTML;
alert("In the loop and " + columnData );
}
if (count == 0) return;
var posturl = '<%= ResolveUrl("~") %>Rel******/AddSelected****/' + ids;
if (confirm("Add these " + count + " Docs?")) {
$.post(posturl,
{ ids: columnData },
function() { jQuery("#relatedSearchGrid").trigger("reloadGrid") },
"json");
}
})
Use getRowData to get the data for each row:
var rowData = $("#relatedSearchGrid").getRowData(ids[i]);
var colData = rowData.Name_Of_Your_Column;
var userListjqGrid = $('#UserListGrid'),
selRowId = userListjqGrid.jqGrid('getGridParam', 'selrow'),
userId = userListjqGrid.jqGrid('getCell', selRowId, 'UserId'),
userName = userListjqGrid.jqGrid('getCell', selRowId, 'UserName'),
subIds = $(subgridTableId).getGridParam('selarrrow'),
accessRuleIds = [];
for (var i = 0; i < subIds.length; i++) {
accessRuleIds[i] = $(subgridTableId).getRowData(subIds[i]).AccessRuleId;
}

Categories