Get objects and values inside an array at the same time - arrays

I'm using AngularJS and a JSON file to hold my data. And my data holds an array with objects and some values.
Here's my JSON:
{
"DirectoryList":
[
{
"_id": 2,
"navLvl": 1,
"codeName": "BOD",
"DirectoryName": "Board of Directors",
"Contacts": [
{
"BodName": "FVC",
"Position": "CEO",
"LocalNo": "101",
"Mobile": ["09178985698", "09178985698"]
},
{
"BodName": "MIC",
"Position": "PRESIDENT",
"LocalNo": "108",
"Mobile": ["09178710088", "09178889088"]
},
{
"BodName": "SIC",
"Position": "SVC-OPTRNS",
"LocalNo": "105",
"Mobile": ["09178923689", "09328922955"]
}
]
}
]
}
And in my controller:
$http.get('./json/directory.json')
.success(function(data){
var result = $filter('filter')(data.DirectoryList, {_id:$stateParams.id})[0];
$scope.listviews = [];
angular.forEach(result, function(value, key) {
$scope.listviews.push(value);
});
})
.error(function(err){
$log.error(err);
})
And in my views:
<div class="table-responsive" ng-if="listviews[0] == 2">
<table class="table table-striped table-hover table-condensed table-bordered">
<tr>
<thead>
<th>BOD Name</th>
<th>Position</th>
<th>Local No.</th>
<th>Mobile</th>
</thead>
</tr>
<tr>
<tbody ng-repeat="list in listviews[4]">
<td ng-repeat="(key, value) in list">{{ value }}</td>
</tbody>
</tr>
</table>
</div>
This gives me:
BOD Name | Position |Local No. | Mobile
---------+----------+----------+-------------------------------
FVC | CEO | 101 | ["09178985698","09178985698"]
---------+----------+----------+-------------------------------
MIC | PRESIDENT| 108 | ["09178710088","09178889088"]
---------+----------+----------+-------------------------------
SIC |SVC-OPTRNS| 105 | ["09178923689","09328922955"]
I have no idea how to display it correctly but when I try to change the value to value[0] I can get the first array but it ruins the data holds by objects. Is there another way getting the data from objects together with values? Can't figure out where should I execute the logic. Is it way better in the controller or in my view?

I'm pretty sure there is a lot of different ways on doing this. The following is one that should work.
<tbody ng-repeat="list in listviews[4]">
<td ng-repeat="(key, value) in list">
<div ng-if="key=='Mobile'" ng-repeat="phone in value">{{phone}} </div>
<div ng-if="key!='Mobile'">{{value}}</div>
</td>
</tbody>

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.

Smart Table search not working when creating multiple tables

This is what I am doing.
I call a rest api which returns response in this format
"metalanguages": {
"1": {
"id": 1,
"name": "Abkhaz"
},
"2": {
"id": 2,
"name": "Afar"
}
},
"manufacturers": {
"-1": {
"id": -1,
"name": "all"
},
"1": {
"id": 1,
"name": "RIM"
},
"2": {
"id": 2,
"name": "HP"
}
}
This is basically a Map of String and Map.
I now have to create n number of table where n is number of keys of original map and inside each table I have to show data which will be the value of internal map ("id": 2,
"name": "HP")
I have made it working but search is not working.
This is my sample code
<div ng-repeat="(key,value) in metadataDetails">
<table st-table="metadataCollection" st-safe-src="metadataDetails" class="table table-striped">
<thead>
<tr class="style_tr">
<th st-sort="name">name</th>
<th st-sort="name">name</th>
<th st-sort="description">description</th>
<th st-sort="countryName">countryName</th>
<th st-sort="carrierName">carrierName</th>
</tr>
<tr class="textSearchTr">
<th colspan="4" class="textSearchTr">
<input class="freshblue" placeholder="Enter value to search/filter" type="text" ng-model="searchParam.search" />
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in getValueMap(key)" ng-show="showRow">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.description}}</td>
</tr>
</tbody>
</table>
</div>
And my js file
AuditMetadataService.get({}, function(data) {
$scope.numRecord = data.length;
$scope.metadataDetails = data;
$scope.metadataCollection = [].concat($scope.metadataDetails);
console.log("Return value :");
console.log($scope.metadataDetails);
});
$scope.getValueMap = function(key) {
console.log(key);
return $scope.metadataDetails[key];
};
Could someone please help??
You can turn your map object into an array by getting it's keys and using the Array.prototype.map function, you will have to repeat this for the inner map objects as well because st-sort expects an array item, not a key value.
$scope.tables = keys.map(function(key) {
return Object.keys(data[key]).map(function(k) {
return data[key][k];
});
});
Then you can iterate $scope.tables using ng-repeat to create all the tables want, clicking the column titles will now sort them properly.
Here is a demo.

Angular add filter based on Object value

I'm starting AngularJS. I'm dynamically building a table with angular and I'm trying to add a filter to one of my columns.
Here the code I have in my controller :
$scope.columns = [
{
"alias":"alias1",
"name":"name1",
"type":"string"
},
{
"alias":"alias2",
"name":"name2",
"type":"currency"
}
];
$scope.data = [
{
"alias1": "value1",
"alias2": "22489"
},
{
"alias1": "value2",
"alias2": "22489"
},
{
"alias1": "value3",
"alias2": "22489"
},
];
And my table looks like this :
<table class="table table-hover">
<thead>
<tr>
<th ng-repeat="c in columns" ng-click="sort(c.alias)">{{ c.name }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="result in results | filter:search | orderBy:sortKey:reverse">
<td ng-repeat="c in columns">{{ result[c.alias] }}</td>
</tr>
</tbody>
</table>
What I'd like to do is to apply a filter to the <td> value based on the type of the column. Something like {{ result[c.alias] | c.type }} doesn't work...
Is it something that can be achieved by some formatting directive for example ?
Thanks for you help.
You mean this?:
app.filter('myfilter', function() {
return function(input, param) {
//do whatever
}
})
{{ result[c.alias] | myfilter:c.type }}

Pagination gets "stuck"?

I have a simple table application that displays dummy data with columns like name, number, date, etc. You can sort it by columns, and it is paginated.
However, when I use the pagination, some of the rows get stuck at the top. It kind of gets sorted alphabetically by the column I intended, but when the page changes (pretend page 4), the rows underneath the first few top rows change, while the very top rows don't budge.
Here is a functional plunker:
HTML:
<pagination class="pagination pagination-sm" items-per-page="itemsPerPage" total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></pagination>
<table class="table table-hover">
<tr>
<th ng-repeat="key in keys" ng-click="sorting.predicate=key;">
{{key}}
</th>
</tr>
<tr ng-repeat="row in data | startFrom:currentRow | orderBy:sorting.predicate:sorting.reverse | limitTo:itemsPerPage">
<td ng-repeat="key in keys">
{{row[key]}}
</td>
</tr>
</table>
Angular:
app.filter('startFrom', function () {
return function (input, start) {
start = +start;
return input.slice(start);
};
});
$scope.data = [{
"id": 0,
"age": 30,
"name": "Trina Pace",
"gender": "female",
"email": "trinapace#darwinium.com",
"phone": "+1 (874) 414-2654"
},etc..];
$scope.keys = Object.keys($scope.data[0]);
$scope.totalItems = $scope.data.length;
$scope.itemsPerPage = 25;
$scope.currentPage = 1;
$scope.currentRow = 0;
$scope.pageChanged = function () {
$scope.currentRow = ($scope.currentPage - 1) * $scope.itemsPerPage;
console.log('current row: ' + $scope.currentRow);
console.log('items per page: ' + $scope.itemsPerPage);
};
$scope.sorting = {predicate:'name',reverse:false};
Am I missing, and/or doing something incorrectly?
Move startFrom:currentRow to after orderBy:sorting.predicate:sorting.reverse.
You want to filter after you sort.
http://plnkr.co/edit/7BbgJ4TMU0pSY8gyDLef?p=preview
<table class="table table-hover">
<tr>
<th ng-repeat="key in keys" ng-click="sorting.predicate=key;">
{{key}}
</th>
</tr>
<tr ng-repeat="row in data | orderBy:sorting.predicate:sorting.reverse | startFrom:currentRow | limitTo:itemsPerPage">
<td ng-repeat="key in keys">
{{row[key]}}
</td>
</tr>
</table>

Get ng-repeat to use object property order

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>

Resources