Smart Table search not working when creating multiple tables - angularjs

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.

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>

Get objects and values inside an array at the same time

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>

A simple mistake in ngInfiniteScroll

I have used ngInfiniteScroll but i have a small problem, i have a set of data in a variable items for eg) 20 but i want to show 5 on first view and the remaining on sliding. but my code loads all the 20 at the first view how can i achieve this, i have given my code below
and my data structure
{
"data": [ {
"name": "Hoarding Majestic",
"code": 456,
"image": "assets/images/images/hoarding1.jpg",
"location": "Majestic"
},
{
"name": "BusShelter ForumMall",
"code": 452,
"image": "assets/images/images/hoarding2.jpg",
"location": "Whitefield"
},
{
"name": "Digital Vijayanagar",
"code": 458,
"image": "assets/images/images/hoarding3.jpg",
"location": "Vijayanagar"
},
{
"name": "Digital Vijayanagar",
"code": 458,
"image": "assets/images/images/hoarding3.jpg",
"location": "Vijayanagar"
}
]
}
html:-
<div layout="row" layout-align="space-around" layout-padding infinite-scroll='loadMore()' infinite-scroll-distance='2'
infinite-scroll-disabled='{{busyLoadingData}}' infinite-scroll-container = "'#content'">
<table class="simple">
<thead>
<tr>
<th class="secondary-text">
<div class="table-header">
<span class="column-title">Asset</span>
</div>
</th>
<th class="secondary-text">
<div class="table-header">
<span class="column-title">Location</span>
</div>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="assets in items">
<!--| priceRange:slider:lower:upper-->
<td>{{assets.name}}</td>
<td>{{ assets.location }}</td>
</tr>
</tbody>
</table>
</div>
and my controller:-
$scope.data = booking.data;
$scope.busyLoadingData = false;
$scope.items = [];
$scope.loadMore = function() {
//console.log("asdfasdfasd");
if($scope.busyLoadingData)
return;
$scope.busyLoadingData = true;
var last = $scope.data[$scope.data.length - 1];
for(var i = 0 ; i <= 5; i++) {
$scope.items.push($scope.data[i]);
//console.log(last);
}
$timeout(function(){$scope.busyLoadingData = false; }, 3000 );
};
Like any infinite scrolling element should do, ng-infinite-scroll is loading more data, than it can display at once. This is to prevent having to less data and having the user reach the bottom even if there is some data left. You can clearly see the effect in this demo. It will start loading data, even if there is still some space left to the bottom of the page.

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