Get ng-repeat to use object property order - angularjs

I have a dynamic dataset to present with Angular. In other words I do not have access to the column names returned until runtime.
I can present the column names as a header and the data itself with no problem. ng-repeat (or perhaps it's JS itself) though refuses to return the columns in the order they were created. You can see in the fiddle the columns are sorted so they appear "age name weight", I need them the way they came, "name age weight"
I created another array of the column names and their proper order ($scope.order) but I cannot seem to find a way to use that with Angular to sort the data.
Please give me a way to present this data in the original order.
I created a JSFiddle: http://jsfiddle.net/GE7SW/
Here's a simple scope that sets up the data:
function MainCtrl($scope) {
$scope.output = [
{
"name": "Tom",
"age": "25",
"weight" : 250
},
{
"name": "Allan",
"age": "28",
"weight" : 175
},
{
"name": "Sally",
"age": "35",
"weight" : 150
}
];
$scope.order = {
"name": 1,
"age": 2,
"weight" : 3
};
}
Here's the HTML:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="(key,value) in output.0">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="(key,value) in row">{{value}}</td>
</tr>
</tbody>
</table>
(Note the (key,value) in the last ng-repeat is needed by ng-class code I took out for this example.)

The properties order in JavaScript objects is never guaranteed. You need to use a list.
The only thing you need to do is convert $scope.order into an array:
$scope.order = [
"name",
"age",
"weight"
];
and use that inside the HTML like this:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="key in order">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="key in order">{{row[key]}}</td>
</tr>
</tbody>
</table>
Fiddle

Your updated fiddle here (click).
While the order of javascript objects is not guaranteed, this is likely to work in most or all cases. This is simply looping your objects into arrays. It might be a better approach, if possible, to have the data coming from the server in arrays, 1 that describes the structure (keys) and the other that just data sets of arrays.
$scope.getRow = function(row) {
var arr = [];
for (var k in row) {
if (k !== '$$hashKey') {
arr.push(row[k]);
}
}
return arr;
};
$scope.getKeys = function(row) {
var arr = [];
for (var k in row) {
if (k !== '$$hashKey') {
arr.push(k);
}
}
return arr;
};
the html:
<table ng-app ng-controller="MainCtrl">
<thead>
<tr>
<th ng-repeat="(key,value) in getKeys(output[0])">{{value}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in output">
<td ng-repeat="(key, value) in getRow(row)" ng-class="getKeys(output[0])[key]">{{value}}</td>
</tr>
</tbody>
</table>

Related

How to sort a nested table that has multiple ng-repeats angularjs

I have searched for a similar example and found lost of examples but none of them have the same datastructure as my json data so I have tried it all without success. This is my json data
vm.result = [
{
'first': [
{"indicate":"all", "text":"All views"},
{"indicate":"userview", "text":"User view"},
{"indicate":"operatorview", "text":"Operator view"}
]
},
{
'second': [
{"indicate":"receipts","text":"Receipts"},
{"indicate":"other", "text":"Other"},
{"indicate":"error", "text":"Error resolver"}
]
}
];
This is my table
<table class="table" >
<thead>
<tr>
<th ng-show="column">Key</th>
<th>Master</th>
<th>Editable</th>
</tr>
</thead>
<tbody ng-repeat="res in vm.result track by $index">
<tr ng-repeat="ed in res.first | filter: searchfield | orderBy: 'indicate' track by $index">
<td {{ed.indicate}}</td>
<td>{{ed.text}}</td>
<td> {{vm.result[1].second[$index].indicate}}</td>
<td > {{vm.result[1].second[$index].text}}</td>
</tr>
</tbody>
</table>
OrderBy only works for the first array but not the second and yes I have tried removing first after re in the second ng-repeat but then it cannot recognize it as an array. I need this structure in the table so that each array has its own columns for its data. So how to I add orderBy indicate for both arrays?
Expected output:
Master Editable
all | All | receipts | Receipts
userview | User view | other |Other
The format of result data is very poor. It is very hard to convert your expected output.
Try to use result array like this or convert to this type of format,
$scope.newResult = [{
first:{"indicate":"all", "text":"All views"},
second:{"indicate":"receipts","text":"Receipts"}
},
{
first:{"indicate":"userview", "text":"User views"},
second:{"indicate":"other","text":"Other"}
},
{
first:{"indicate":"operatorview", "text":"Operator views"},
second:{"indicate":"error","text":"Error resolver"}
}
]
HTML Code
<table >
<thead>
<tr>
<th>Key</th>
<th colspan="2">Master</th>
<th colspan="2">Editable</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="res in new">
<td>{{$index+1}}</td>
<td>{{res.first.indicate}}</td>
<td>{{res.first.text}}</td>
<td>{{res.second.indicate}}</td>
<td>{{res.second.text}}</td>
</tr>
</tbody>
</table>
Controller
$scope.result = [
{
'first': [
{"indicate":"all", "text":"All views"},
{"indicate":"userview", "text":"User view"},
{"indicate":"operatorview", "text":"Operator view"}
]
},
{
'second': [
{"indicate":"receipts","text":"Receipts"},
{"indicate":"other", "text":"Other"},
{"indicate":"error", "text":"Error resolver"}
]
}
];
$scope.new=[];
angular.forEach($scope.result, function(value, key) {
if(key ===0){
angular.forEach(value.first, function(val, k) {
$scope.new.push({'first':val,'second':''});
})
}
if(key ===1){
angular.forEach(value.second, function(val, k) {
$scope.new[k].second = val;
})
}
});
Using this type of mechanism you can get the expected output, but the better way is using good data format for result array.
jsfiddle for this.

Ng-repeat and ng-if usage for html td

I receive a Json that looks like this (I dont have access to change it)
{
"name": "mike"
"days": [
{
"timeperiods": [
{
"time": "08:00 - 12:00",
"hours": 4,
"task": "running"
},
{
"time": "13:00 - 15:00",
"hours": 4,
"task": "triathlon"
}
]
},
{
"timeperiods": [
{
"time": "08:00 - 12:00",
"hours": 3,
"task": "swimming"
}
]
}
]
}
Its not an full JSON-Example. Usually there would be 6 days objects. But i think showing 2 Objects should show my problem.
I create an table in html which shows me what tasks an user has on certain days.
(I save the JSON Data in a scope variable with the name weekplan.)
<table>
<thead>
<tr>
<th>Time</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wedesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="day in weekplan.days[0].timeperiods">
<td>{{day.time}}</td>
<td ng-if="day.hours == 0"><div></div></td>
<td ng-if="day.hours != 999 && day.hours != 0">Time for Workout!!</td>
</tr>
</tbody>
</table>
It can only be one ng-if true never both.
My Problem is to display the Columns correctly. This table example works but only for the time column and the monday column. But i dont know how to get it to work on all weekdays. I thought about using ng-if and ng-repeat on the same td object but it didnt really work out. (I need both ng-if for CSS rules which i have removed from this example cause its not part of the problem). What i want in the End is a table which either shows an empty field for a certain timeperiod or a field where it says "Time for Workout". And this for all Weekdays.
You have very confusing description, but if logically present your json it will look something like:
HTML
<table>
<thead>
<tr>
<th>Time</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wedesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="day in weekplan.days">
<td data-ng-repeat="period in day.timeperiods">
<span>{{day.time}}</span>
<span ng-if="day.hours == 0"></span> <!-- why it is even exist? -->
<span ng-if="day.hours != 999 && day.hours != 0">Time for Workout!! </span>
</td>
</tr>
</tbody>
</table>

How to display json data in two columns in a table using angular

I have data in my json it will be dynamic and I want to display the data in a table with two columns. I am trying but only the first two records are repeating. I don't see all the records in the table.. Any help?
http://plnkr.co/edit/Hnb7hkjA16XDbzRT8VAt?p=preview
This is my json : var data = '{
"output":{
"service-status":[
{
"service":"db",
"service-name":"Mongo DB"
},
{
"service":"license",
"service-name":"Smart License"
},
{
"service":"BRM",
"service-name":"Billing"
},
{
"service":"subscription",
"service-name":"subscription"
}
]
}
}';
my html code:
<table border="1px" width="100%" ng-repeat="data in serviceData" ng-if="$index % 2 == 0">
<tr>
<td>{{serviceData[index]["service-name"]}}</td>
</tr>
</table>
i want to display something like this
Mongo Db Smart License
Billing subscription
Transform your data in the controller:
var serviceDataView = function() {
var res = [];
for (var i = 0; i < $scope.serviceData.length; i+=2){
res.push({
col1: $scope.serviceData[i]['service-name'],
col2: $scope.serviceData[i+1] ? $scope.serviceData[i+1]['service-name'] : null
});
}
return res;
};
$scope.structuredData = serviceDataView();
So that it can be easily used in the view:
<table border="1px" width="100%">
<tr ng-repeat="data in structuredData">
<td>{{data.col1}}</td>
<td>{{data.col2}}</td>
</tr>
</table>
Plunker.
The iterator that uses ng-repeat is $index.
Others Iterator: https://docs.angularjs.org/api/ng/directive/ngRepeat
Replace your table for:
<table border="1px" width="100%" ng-repeat="data in serviceData">
<tr>
<td>{{serviceData[$index]["service"]}}</td>
<td>{{serviceData[$index]["service-name"]}}</td>
</tr>
</table>
As per my review, $index is not required at all for this issue. You can use filter for table ngRepeat.check this [link]http://plnkr.co/edit/Hnb7hkjA16XDbzRT8VAt?p=preview
html code here:
<table border="1px" width="100%" ng-repeat="data in serviceData |limitTo:2 ">
<tr>
<td>{{data["service-name"]}}</td>
<td>{{data.service}}</td>
</tr>

How to use ng-repeat for array in array using single ng-repeat

I got a json of table which has columns and rows as below
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
, Rows:[{Items:[{Value:1},{Value:5},{Value:8},{Value:""}]}
,{Items:[{Value:2},{Value:6},{Value:9},{Value:""}]}
,{Items:[{Value:3},{Value:7},{Value:10},{Value:15}]}]
} //end of table
I want to display Columns.SubHeaders as Sub header row of a table.
Here what I tried, but did not work
<table class="table table-stripped table-bordered">
<thead>
<tr>
<th ng-repeat="col in table.Columns" colspan="{{col.SubHeaders.length}}">{{col.Header}}</th>
</tr>
<tr>
<td class="center text-black" ng-repeat="head in table.Columns[0].SubHeaders">{{head}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in table.Rows">
<td ng-repeat="item in row.Items">
{{item.Value}}
</td>
</tr>
</tbody>
</table>
I used head in table.Columns[0].SubHeaders just to show it is working for hard-coded index value.
How can I achieve this using single ng-repeat? I can use two ng-repeats but it will lead to unnecessary html markup.
Here is the complete fiddle
I created this fiddler (forked from yours):
https://jsfiddle.net/b50hvzef/1/
The idea is to join the subheaders as they are they actual columns:
<td class="center text-black" ng-repeat="head in subHeaders">{{head}}</td>
and the code looks like this:
var app = angular.module("app",[]);
app.controller("MyController", function ($scope, $http) {
$scope.table = {
Columns: [{Header:"22-Jul-15",SubHeaders: ["10:33 AM"]}
, {Header:"21-Jul-15",SubHeaders: ["03:40 AM"]}
, {Header:"17-Jul-15",SubHeaders: ["01:05 PM", "12:06 PM"]}]
,Rows:[{Items:[{Value:1},{Value:5},{Value:8}]}
,{Items:[{Value:2},{Value:6},{Value:9}]}
,{Items:[{Value:3},{Value:7},{Value:10}]}]
};
var subHeaders = [];
$scope.table.Columns.forEach(function(col) {
col.SubHeaders.forEach(function(subHeader) {
subHeaders.push(subHeader);
});
});
$scope.subHeaders = subHeaders;
});
Note that there is still a mismatch between columns and data. But it's up to you how to solve it.
Hope this helps.

ng-repeat on array of objects not working..?

I have an array of objects like this:
var data = [{
"id": 1,
"age": 20,
"name": "Janell Mcintosh",
"gender": "female",
"email": "janellmcintosh#zilphur.com",
"phone": "+1 (906) 555-2575"
},etc..
];
var keys = Object.keys(data[0]);
I am trying to display this data in a table. The keys are columns, and all of the object's values are supposed to go in the relevant column. Here is what I am trying:
<table class="table table-striped">
<tr>
<th ng-repeat="key in keys">
{{key}}
</th>
</tr>
<tr ng-repeat="row in data">
<td ng-repeat="key in keys">
{{row['"'+key+'"']}}
</td>
</tr>
</table>
This doesn't work. I am trying to put quotes around the key because the JSON I receive has the keys and values in quotes. The data/variables are stored properly, I just don't know how to access them.
Am I doing something incorrectly here?
{{row['"'+key+'"']}}
I'm just trying to add quotes to the key.
View sample plunker here:
You don't need the double-quotes around the key values. (Javascript parses keys the same whether or not the quotes are present, so var data = { "id": 1 } is completely equivalent to var data = { id: 1 }.
So all you need is:
<td ng-repeat="key in keys">
{{row[key]}}
</td>
See here.

Resources