angular ng-repeat through multi level object - javascript

I have an object that has different objects within in, here is an example of the object
{
"0":{
"name":{
"type":"unchanged",
"data":"HV010BSML"
},
"colour":{
"type":"unchanged",
"data":"BLACK"
},
"size":{
"type":"unchanged",
"data":"SML"
},
"qty":{
"type":"unchanged",
"data":1
},
"localimg":{
"type":"unchanged",
"data":"/data/New%20Products/HV010%20Black%20with%20pocket%20WM-700x700.jpg"
},
"sml":{
"type":"unchanged",
"data":"2"
},
"stock":{
"type":"unchanged",
"data":"78"
},
"id":{
"type":"unchanged",
"data":"153"
},
"name2":{
"type":"unchanged",
"data":"HV010"
}
},
"1":{
"type":"created",
"data":{
"name":"HV001YSML",
"colour":"YELLOW",
"size":"SML",
"qty":1,
"localimg":"/data/HV001-HV-VEST-YLW-700x700.jpg",
"sml":"1",
"stock":"424",
"id":"8",
"name2":"HV001"
}
}
}
Im wondering if it is possible to iterate over each of these using ng-repeat, because its an object within an object? Ive created a table with ng-repeat and in the "change" col i want to do another ng repeat (which uses the object i showed above) but when i try to show the data in the html its just printing every letter of the array. I'm basically trying to ng-repeat through the object[0] and show it in a readable format such as "HV010BSML is unchanged"
Here is my html :
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-content">
<table datatable="ng" dt-options="dtOptions" class="table table-striped table-bordered table-hover dataTables-example">
<thead>
<tr>
<th>User</th>
<th>Date</th>
<th>Change</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(oIndex, o) in orderdata">
<td>{{o.user}}</td>
<td>{{o.date}}</td>
<td> <div ng-repeat="d in formatdata(findhistory(oIndex)) track by $index">{{d}}</div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
In the controller, findhistory just returns that object i showed and formatdata is this function in the controller
$scope.formatdata=function(obj){
try{
if(obj[0]){
console.log(JSON.stringify(obj[0]));
return JSON.stringify(obj[0]);
}
else{
return;
}
}
catch(ex){}
}

Iterating over object properties
It is possible to get ngRepeat to iterate over the properties of an
object using the following syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>
However, there are a few limitations compared to array iteration:
The JavaScript specification does not define the order of keys returned for an object, so AngularJS relies on the order returned by
the browser when running for key in myObj. Browsers generally follow
the strategy of providing keys in the order in which they were
defined, although there are exceptions when keys are deleted and
reinstated. See the MDN page on delete for more info.
ngRepeat will silently ignore object keys starting with $, because it's a prefix used by AngularJS for public ($) and private ($$)
properties.
The built-in filters orderBy and filter do not work with objects, and will throw an error if used with one.
If you are hitting any of these limitations, the recommended
workaround is to convert your object into an array that is sorted into
the order that you prefer before providing it to ngRepeat. You could
do this with a filter such as toArrayFilter or implement a $watch on
the object yourself.
Extracted from the Angularjs API reference
Personally, i think you could benefit from a little change in your data source, instead of a object holding everything together, use a collection with some similar objects inside. It's easier to understand and has a better support with the ngRepeat.
How about something like this:
[
{
"id": "0",
"data": [
{
"property": "name",
"type":"unchanged",
"data":"HV010BSML"
},
{
"property": "colour",
"type":"unchanged",
"data":"BLACK"
},
{
"property": "size",
"type":"unchanged",
"data":"SML"
},
{
"property": "qty",
"type":"unchanged",
"data":1
},
{
"property": "localimg",
"type":"unchanged",
"data":"/data/New%20Products/HV010%20Black%20with%20pocket%20WM-700x700.jpg"
},
{
"property": "sml",
"type":"unchanged",
"data":"2"
},
{
"property": "stock",
"type":"unchanged",
"data":"78"
},
{
"property": "id",
"type":"unchanged",
"data":"153"
},
{
"property": "name2",
"type":"unchanged",
"data":"HV010"
}
]
},
{
"id": "1"
"data": [
{
"type":"created",
"data":{
"name":"HV001YSML",
"colour":"YELLOW",
"size":"SML",
"qty":1,
"localimg":"/data/HV001-HV-VEST-YLW-700x700.jpg",
"sml":"1",
"stock":"424",
"id":"8",
"name2":"HV001"
}
}
]
}
]

Related

How to get a specific or multiple values (or keys) from nested JSON

I have a (nested) data structure containing objects and arrays. How can I extract the information, i.e. access a specific or multiple values (or keys)?
{
"data": [{
"name": "name1",
"value": "value1",
"list": [{
"sname": "sname1",
"svalue": "svalue1"
}, {
"sname": "sname2",
"svalue": "svalue2"
}]
}]
}
jQuery
var pk = $("#pk").val();
console.log(pk);
url = "/register/search?id=" + pk;
console.log(url);
$('#largeTable').DataTable({
"ajax": url,
"bDestroy": true,
"columns": [{
"data": "name"
},
{
"data": "value"
},
{
"data": "list.1.sname"
},
{
"data": "list.1.svalue"
},
{
"data": null,
"defaultContent": editview
}
]
});
Here it is possible to display either first or second list values by using list.1 or list.0
But I want two values at a time.
Also, how could I access the svalue of the second item in list?
I tried with data.list[1] but:
TypeError: data.list is undefined
Since data is an array, you should first get the item - and since you only have one item - you'd use data[0], and then get access to the list property like data[0].list[1] - this will give you the second item in the list - but since you are interested in a specific property (svalue) of this item, you will then access it like this: data[0].list[1].svalue.
A better approach would be to loop through the items in the data array - and then for each item, loop through the items in the list array. See #Rajesh's comment.
I hope that helps;
Specifically you can access it like this object.data[0].list[1].svalue. The reason data.list is undefined is because data corresponds to an array data: [{ }] this is why we use data[0], but data itself is a key in an object so before you can get to data you need to access it. If the objects name where data resides were object (like I did below) then it'd be accessed like this object.data[0]
const object = {
"data": [{
"name": "name1",
"value": "value1",
"list": [{
"sname": "sname1",
"svalue": "svalue1"
}, {
"sname": "sname2",
"svalue": "svalue2"
}]
}]
}
console.log(object.data[0].list[1].svalue)

Javascript dataTables populating data issue (no errors returned)

I am using data tables and trying to popular a table with data.
The data I have looks like this:
<table id="mytable" class="display" width="100%"></table>
{
"users": [
{
"id": "6700",
"user": {
"firstName": "somename"
},
"Count": 0
}
]
}
So this is what I've done:
var dataSet = {
"users": [
{
"id": "6700",
"user": {
"firstName": "somename"
},
"Count": 0
}
]
};
jQuery('#mytable').DataTable( {
data: dataSet,
columns: [
{ "users": "id" }
]
});
I'm am not getting any errors but the data is not inserted either.
What I'm I doing wrong here?
In data option you need to provide variable that contains array of objects (dataSet.users). Also in columns.data option you need to define property within each object in the array (id).
Corrected code is shown below.
jQuery('#mytable').DataTable( {
"data": dataSet.users,
"columns": [
{ "data": "id", "title": "ID" }
]
});
See this example for demonstration.

Efficient way to Populate Table with multidimensional JSON

I'm looking to the most efficient way to convert this json.
{
"Kitchen":{
"protocol":[
"pollin"
],
"id":[
{
"systemcode":31,
"unitcode":1
}
],
"state":"off"
},
"BBQ":{
"protocol":[
"pollin"
],
"id":[
{
"systemcode":31,
"unitcode":4
}
],
"state":"off"
},
"Server":{
"protocol":[
"pollin"
],
"id":[
{
"systemcode":15,
"unitcode":1
}
],
"state":"off"
}
}
Into the following table:
[Name] [Protocol] [Systemcode] [S] [State]
Kitchen pollin 31 1 off
BBQ pollin 31 4 off
Server pollin 15 1 off
My page consists of a table in html and jquery is already loaded.
<table class="table" id="tableDevices">
<thead>
<tr>
<th>Name</th>
<th>Protocol</th>
<th>Systemcode</th>
<th>Unitcode</th>
<th>State</th>
</tr>
</thead>
</table>
Now I'm looking for the fastest way to loop trough the JSON, and populate the table with the data. I first flattened the JSON, and then fed it to the table with a loop. However the code I modified to flatten the JSON was painfully slow. This is the my first time working with version control and javascript and I apparently didn't commit my code properly. I'm looking for the most efficient way to fill this table and I'm stuck myself so can someone show my the most efficient way to do this?
I'm going to assume you've parsed the JSON and have a variable, data, that refers to the parsed result.
Then it's a simple for-in loop:
var tbody = $("<tbody>");
var key, entry, tr;
for (key in data) {
entry = data[key];
tr = $("<tr>");
$("<td>").text(key).appendTo(tr);
$("<td>").text(entry.protocol[0]).appendTo(tr);
$("<td>").text(entry.id[0].systemcode).appendTo(tr);
$("<td>").text(entry.id[0].unitcode).appendTo(tr);
$("<td>").text(entry.state).appendTo(tr);
tr.appendTo(tbody);
}
tbody.appendTo("#tableDevices");
That said, you might look at a templating library like Handlebars instead.
Live Example:
// This stands in for the parsed JSON
var data = {
"Kitchen": {
"protocol": [
"pollin"
],
"id": [{
"systemcode": 31,
"unitcode": 1
}],
"state": "off"
},
"BBQ": {
"protocol": [
"pollin"
],
"id": [{
"systemcode": 31,
"unitcode": 4
}],
"state": "off"
},
"Server": {
"protocol": [
"pollin"
],
"id": [{
"systemcode": 15,
"unitcode": 1
}],
"state": "off"
}
};
var tbody = $("<tbody>");
var key, entry, tr;
for (key in data) {
entry = data[key];
tr = $("<tr>");
$("<td>").text(key).appendTo(tr);
$("<td>").text(entry.protocol[0]).appendTo(tr);
$("<td>").text(entry.id[0].systemcode).appendTo(tr);
$("<td>").text(entry.id[0].unitcode).appendTo(tr);
$("<td>").text(entry.state).appendTo(tr);
tr.appendTo(tbody);
}
tbody.appendTo("#tableDevices");
<table class="table" id="tableDevices">
<thead>
<tr>
<th>Name</th>
<th>Protocol</th>
<th>Systemcode</th>
<th>Unitcode</th>
<th>State</th>
</tr>
</thead>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Note that the JSON structure is fairly odd. You have arrays lying around that have just one entry in them.
Why not use Datables instead? You will have most of the burden of populating the table lifted from your shoulders.

DataTables - Uncaught TypeError: Cannot read property 'length' of undefined

I've seen several examples of this problem but still haven't been able to find a resolution.
The error says it breaks on jquery.dataTables.js (version 1.10.4) on line 3287 shown below
// Got the data - add it to the table
for ( i=0 ; i<aData.length ; i++ ) {
_fnAddData( settings, aData[i] );
}
This is my controller. The controller is this way because the the lack of db connection right now, but will have JSON returned in the same format as $data. I have tried several things to resolve the error, but keep running into other issues. The JSON IS valid.
public function test()
{
$data = '{"persons": [{"branch": "CORP","phone_numbers": [{"desk": "5223422117"},{"mobile": "5022319224"},{"branch": "422-922-2291"}],"email": "twilliams#test.com","preferred_name": "Thomas","person_id": 368,"department": "IT","first_name": "Thomas","title": "Programming Manager","last_name": "Williams"}]}';
$data = json_encode($data);
echo $data;
}
My javascript
$(document).ready(function() {
$('#directory_table').dataTable( {
"ajax": {
"url": "test",
"type": "JSON"
},
"aoColumns": [
{ "persons": "preferred_name" },
{ "persons": "last_name" },
{ "persons": "phone_numbers.0" },
{ "persons": "phone_numbers.1" },
{ "persons": "phone_numbers.2" },
{ "persons": "email" },
{ "persons": "department" },
{ "persons": "title" }
]
} );
} );
My HTML
<table id='directory_table' class="display">
<thead>
<tr style='background: #186A9F; color: white;'>
<th>First Name </th>
<th>Last Name</th>
<th>Desk Number</th>
<th>Mobile</th>
<th>Branch</th>
<th>Email</th>
<th>Department</th>
<th>Title</th>
</tr>
<thead>
</table>
CAUSE
By default DataTables expects JSON response to have certain structure, see documentation.
Array of arrays:
{
"data": [
[ "value1", "value2" ],
...
]
}
Array of objects:
{
"data": [
{
"attr1": "value1",
"attr2": "value2"
},
...
]
}
Error occurs because name of the data property in your response holding array of objects (persons) differs from default (data).
SOLUTION
Use ajax.dataSrc option to define the property from the data source object (i.e. that returned by the Ajax request) to read.
$('#directory_table').dataTable( {
"ajax": {
"url": "test",
"dataSrc": "persons"
},
"columns": [
{ "data": "preferred_name" },
{ "data": "last_name" },
{ "data": "phone_numbers.0.desk" },
{ "data": "phone_numbers.1.mobile" },
{ "data": "phone_numbers.2.branch" },
{ "data": "email" },
{ "data": "department" },
{ "data": "title" }
]
});
Alternatively if you can change data property name in JSON response from persons to data, then adding "dataSrc": "persons" wouldn't be needed.
DEMO
See this jsFiddle for code and demonstration.
LINKS
See jQuery DataTables: Common JavaScript console errors for more information on this and other common console errors.

Looping json object key => array

I'm pulling in a json object, this is the result of a $.parseJSON output. I understand it needs a handler to help it but not to sure what belongs in the helper. Reading the other users questions, they seem to be able to jump through the next hoop due to having a constant key, unfortunately in my case it's always different.
Json output
[
{
"High blood pressure?": [
"no",
"string"
]
},
{
"Cancer?": [
"no",
"string"
]
},
{
"Asthma or a breathing disorder?": [
"no",
"string"
]
}
]
Loop
{{#each screen_data}}
<tr>
<td class="bold">{{this}}</td>
</tr>
{{/each}}
Results in
[Object object][Object object][Object object]......
It's because you've got an array of objects, and that's what you're telling your template to write out.. the object. It seems like you want to write out the only property on the root of the object, which is a question.
try this:
{{#each screen_data}}
<tr>
<td class="bold">{{this[0]}}</td>
</tr>
{{/each}}
That's a strange JSON structure you have there, I must say. Generally it's considered poor form to use the object property name as a carrier of data like that.
EDIT: I'd recommend changing that structure to something that better represents your data... like so:
[{
question: "High blood pressure?",
answers: [
"no",
"string"
]
},
{
questions: "Cancer?",
answers: [
"no",
"string"
]
},
{
question: "Asthma or a breathing disorder?",
answers: [
"no",
"string"
]
}]
Which would then mean your template would look like so:
{{#each screen_data}}
<tr>
<td class="bold">{{this.question}}</td>
</tr>
{{/each}}
You can try this fiddle below. It will give you all the keys from the JSON data
http://jsfiddle.net/tariqulazam/SjugS/
var data= [
{
"High blood pressure?": [
"no",
"string"
]
},
{
"Cancer?": [
"no",
"string"
]
},
{
"Asthma or a breathing disorder?": [
"no",
"string"
]
}
];
for (var key in data) {
for (var item in data[key]) {
alert(item);
}
}

Categories

Resources