Angular repeat structure based on value - angularjs

I have a following json structure that I would like to turn into table.
What would be the best approach here? Groups 1 and -1 would represent Positive and Negative respectivly. These can or cannot be presented in data, but must be defined in table.
Expected result
| Very Positive | Positive | Neutral | Negative | Very Negative |
-----------+---------------+----------+---------+----------+---------------|
Cleaniness | 16 | 0 | 11 | 0 | 30 |
Staff | 20 | 0 | 15 | 0 | 37 |
-----------+---------------+----------+---------+----------+---------------|
Data:
{
"Cleanliness": [
{
"group": "-2",
"count": 30
},
{
"group": "0",
"count": 11
},
{
"group": "2",
"count": 16
}
],
"Staff": [
{
"group": "-2",
"count": 37
},
{
"group": "0",
"count": 15
},
{
"group": "2",
"count": 20
}
]
}
Any help appreciated, thanks in advance!

You can do using ngRepeat on a fixed array of values ng-repeat="pos in [2, 1, 0, -1, -2]":
var app = angular.module('demo', []);
app.controller('demoCtrl', function() {
var stats = {
"Cleanliness": [{
"group": "-2",
"count": 30
}, {
"group": "0",
"count": 11
}, {
"group": "2",
"count": 16
}],
"Staff": [{
"group": "-2",
"count": 37
}, {
"group": "0",
"count": 15
}, {
"group": "2",
"count": 20
}]
};
/** we want to transform original data to this structure
[{
name: "Cleanliness",
data: {
'-2': 30,
'0': 11,
'2': 16
}
}, {
name: "Staff",
data: {
'-2': 37,
'0': 15,
'2': 20
}
}]
**/
this.stats = Object.keys(stats).map(function(category) {
return {
name: category,
data: stats[category].reduce(function(obj, stat) {
obj[stat.group] = stat.count;
return obj;
}, {})
};
});
});
table {
border-collapse: collapse;
}
th,
td {
padding: 0 3px;
border: 1px solid blue;
}
td:not(:first-child) {
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo" ng-controller="demoCtrl as demo">
<table>
<thead>
<tr>
<th></th>
<th>Very Positive</th>
<th>Positive</th>
<th>Neutral</th>
<th>Negative</th>
<th>Very Negative</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="category in demo.stats">
<td>{{category.name}}</td>
<td ng-repeat="pos in [2, 1, 0, -1, -2]">
{{category.data[pos] || 0}}
</td>
</tr>
</tbody>
</table>
</div>

Related

AngularJS loop variable not working as expected

The JSFiddle for this code is at http://jsfiddle.net/done_merson/x3r4o0aj/7/.
Here is the HTML:
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="category in model.categories"> <span> Category: {{ category.name }} </span>
<p ng-repeat="subCategory in getSubCategories(category.Id)">{{ subCategory.name }}
<p ng-repeat="subsubCategory in getSubSubCategories(subCategory.name)">{{ subsubCategory.amount }}
</p>
</div>
</div>
And here is the the JS code:
angular.module("app", [])
.controller('ctrl', ['$scope',
function ($scope) {
$scope.model = {
categories: [{
"Id": 1,
name: '1'
}, {
"Id": 2,
name: '2'
}],
subCategories: [{
"parentId": 1,
name: 'a1'
}, {
"parentId": 1,
name: 'a2'
},
{
"parentId": 2,
name: 'a3'
}],
subsubcategories:[
{
"name":'a1',
"amount": 43
},
{
"name":'a1',
"amount": 21
},
{
"name":"a2",
"amount": 25
},
{
"name":"a3",
"amount": 33
},
{
"name":"a3",
"amount": 17
}
]
}
$scope.getSubCategories = function(parentId){
var result = [];
for(var i = 0 ; i < $scope.model.subCategories.length ; i++){
if(parentId === $scope.model.subCategories[i].parentId){
result.push($scope.model.subCategories[i]);
}
}
console.log(parentId)
return result;
}
$scope.getSubSubCategories = function(name){
var subresult = [];
for(var i = 0 ; i < $scope.model.subsubcategories.length ; i++){
if(name === $scope.model.subsubcategories[i].name){
subresult.push($scope.model.subsubcategories[i]);
}
}
console.log(name)
return subresult;
}
}])
The first loop is working correctly (model.categories) but inner loop for the next loop is passing undefined for subCategory.name. Can I not pass the subCategory to the next loop? Or am I doing something wrong? What I am really trying to do is be able to create a report like you can with Access or ReportServer where you have grouping and summary of data. If anyone has any code like, I would love to see an example too.
Check now
angular.module("app", [])
.controller('ctrl', ['$scope',
function ($scope) {
$scope.model = {
categories: [{
"Id": 1,
name: '1'
}, {
"Id": 2,
name: '2'
}],
subCategories: [{
"parentId": 1,
name: 'a1'
}, {
"parentId": 1,
name: 'a2'
},
{
"parentId": 2,
name: 'a3'
}],
subsubcategories:[
{
"name":'a1',
"amount": 43
},
{
"name":'a1',
"amount": 21
},
{
"name":"a2",
"amount": 25
},
{
"name":"a3",
"amount": 33
},
{
"name":"a3",
"amount": 17
}
]
}
$scope.getSubCategories = function(parentId){
var result = [];
for(var i = 0 ; i < $scope.model.subCategories.length ; i++){
if(parentId === $scope.model.subCategories[i].parentId){
result.push($scope.model.subCategories[i]);
}
}
console.log(parentId)
return result;
}
$scope.getSubSubCategories = function(name){
var subresult = [];
for(var i = 0 ; i < $scope.model.subsubcategories.length ; i++){
if(name === $scope.model.subsubcategories[i].name){
subresult.push($scope.model.subsubcategories[i]);
}
}
console.log(name)
return subresult;
}
}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="category in model.categories"> <span> Category: {{ category.name }} </span>
<p ng-repeat="subCategory in getSubCategories(category.Id)">{{ subCategory.name }}
<span ng-repeat="subsubCategory in getSubSubCategories(subCategory.name)">{{ subsubCategory.amount }} </span>
</p>
</div>
</div>
You have invalid html -- change inner p to span (also add </span>) and it will work.
Errors in html doesnt always result in such tricky things, but its better to always keep it valid.

Pagination of nested objects in angular js

I am starting out with angular and I have a nested object which i would like to paginate. The items to be paginated are some of the 'attributes' in the given object. The queuelist object is nested with array within array. Any help would be appreciated.
The plunker link for non-paginated data is:
https://plnkr.co/edit/zgo0msd6y5ba6DJ6qGlc?p=preview
app.js:
var app = angular.module("myApp",[])
.controller("mycontroller",['$scope',function($scope){
$scope.queuelist = [
{
"name": "ONE",
"QueueList": [
{
"id": 1,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:64"
},
{
"id": 2,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:65"
},
{
"id": 3,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:66"
}
],
"$$hashKey": "object:59"
},
{
"name": "TWO",
"QueueList": [
{
"id": 4,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:72"
},
{
"id": 5,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:73"
},
{
"id": 6,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:74"
},
{
"id": 7,
"attributes": {
"a": 1,
"b": "2017-07-25T12:57:06Z",
"c": 1500967626000,
"d": "asdasd",
"e": "aasdasdasd",
"f": 0
},
"$$hashKey": "object:75"
}
],
"$$hashKey": "object:60"
}
];
$scope.objects = [];
/*
for(i=0;i<$scope.data.length;i++){
$scope.data2.push($scope.data[i].QueueList);
};
*/
for(i=0;i<$scope.queuelist.length;i++){
for(j=0;j<$scope.queuelist[i].QueueList.length;j++){
$scope.objects.push($scope.queuelist[i].QueueList[j].attributes);
};
};
}])
and index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script type= "text/javascript" src= "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
<script type= "text/javascript" src= "app.js"></script>
<style>
table, td, th {
border: 1px solid #ddd;
text-align: left;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 15px;
}
</style>
</head>
<body>
<div ng-controller="mycontroller">
<div ng-repeat="queueJob in queuelist">
{{queueJob.name}}
<table>
<thead>
<tr>
<th><b>a</b></th>
<th><b>b</b></th>
<th><b>c</b></th>
<th><b>e</b></th>
<th><b>f</b></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="queue in queueJob.QueueList">
<td>{{queue.attributes.a}}</td>
<td>{{queue.attributes.b}}</td>
<td>{{queue.attributes.c}}</td>
<td>{{queue.attributes.e}}</td>
<td>{{queue.attributes.f}}</td>
</tr>
<br/><br/>
</tbody>
</table>
<br/><br/>
<br/><br/>
</div>
</div>
</body>
</html>
You can do this using a combination of:
A custom filter (to determine how many records to skip), and...
The built in limitTo filter (to limit the number of records to the desired page size)
1) First create the custom filter.
app.filter("startFrom", function thisFilter() {
return function(input, index) {
return input.slice(parseInt(index));
};
});
The filter takes in an index which it goes on to use in the Array.prototype.slice() method. The slice() method slices the array at the given index and returns a new array containing all remaining objects. The filter returns the new array.
2) Use the custom filter and built-in limitTo filter in the ng-repeat directive.
<tr ng-repeat="queue in queueJob.QueueList | startFrom: queueJob.pageIndex | limitTo: 1">
Here we use the newly created startFrom custom filter passing it the queueJob.pageIndex property as the filter's index parameter. We pass the results of the startFrom filter onto the limitTo filter which reduces the number of records to 1.
Note: We have to use the pageIndex property on the queueJob itteration variable because this ng-repeat is contained within another ng-repeat and so a $scope.pageIndex variable would have been conflicted and subsequently overwritten.
3) Create next and previous buttons
<tr>
<td colspan="5">
<button class="btn"
ng-click="onPrevClicked(queueJob)"
ng-disabled="isFirst(queueJob)">
<span class="fa fa-chevron-left"></span>
Prev
</button>
<button class="btn"
ng-click="onNextClicked(queueJob)"
ng-disabled="isLast(queueJob)">
Next
<span class="fa fa-chevron-right"></span>
</button>
Page {{ queueJob.pageIndex + 1 }}
</td>
</tr>
Here we use ng-click directives to invoke controller functions that increment/decrement the queueJob object's pageIndex property. We also use ng-disabled directives to prevent navigating next/previous if the user is on the first/last record.
4) Create the bindable functions in the controller
$scope.onPrevClicked = onPrevClicked;
$scope.onNextClicked = onNextClicked;
$scope.isFirst = isFirst;
$scope.isLast = isLast;
function onPrevClicked(obj) {
if (!isFirst(obj)) obj.pageIndex--;
}
function onNextClicked(obj) {
if (!isLast(obj)) obj.pageIndex++;
}
function isFirst(obj) {
return obj.pageIndex === 0;
}
function isLast(obj) {
return obj.pageIndex + 1 === obj.QueueList.length;
}
5) Initialise the pageIndex properties upfront
$scope.queuelist.forEach(function(obj) {
obj.pageIndex = 0;
});
This initialised the pageIndex as a number that can be incremented and subsequently decremented.
Demo
CodePen: Using a custom filter to do pagination

to order object contain dates in html view by angularjs

I have to arrange status(P,A) according to date in ascending order but it showing me in same order as they are inserted. but i want to arrange accourding to date.
API Data:-
$scope.students{
"name": "sample",
"def": [
{
"setId": "arun",
"Date": [
{
"day": "2016-09-28",
"status": "A"
},
{
"day": "2016-09-27",
"status": "P"
},
{
"day": "2016-09-29",
"status": "A"
},
{
"day": "2016-09-26",
"status": "P"
}
]
},
{
"name": "deepak",
"Date": [
{
"day": "2016-09-28",
"status": "P"
},
{
"day": "2016-09-27",
"status": "A"
},
{
"day": "2016-09-29",
"status": "A"
},
{
"day": "2016-09-26",
"status": "P"
},
]
}
]
}
html page :-
<table>
<tbody>
<tr>
<td>S.No.</td>
<td>NAME</td>
<td>26-9-2016</td>
<td>27-9-2016</td>
<td>28-9-2016</td>
<td>29-9-2016</td>
</tr>
<tr data-ng-repeat="student in students" st-select-row="row">
<td data-ng-bind="$index+1"></td>
<td data-ng-bind="student.name"></td>
<td data-ng-repeat="data in student.Date" data-ng-bind="data.status"></td>
</tr>
</tbody>
</table>
want to show on screen in this way:
1. Name | 26-9-2016 | 27-9-2016 | 28-9-2016 | 29-9-2016|
2. Arun | P | P | A | A |
3. dDepak | P | A | P | A |
but i am getting in this way on screen :
1. Name | 26-9-2016 | 27-9-2016 | 28-9-2016 | 29-9-2016|
2. Arun | A | P | A | p |
3. Deepak | P | A | A | P |
angular.module('myApp', ['ng'])
.controller('Ctrl', ['$scope',
function($scope) {
$scope.students = {
"name": "sample",
"def": [{
"name": "arun",
"Date": [
{
"day": "2016-09-28",
"status": "A"
}, {
"day": "2016-09-27",
"status": "P"
},
{
"day": "2016-09-29",
"status": "A"
},
{
"day": "2016-09-26",
"status": "P"
}
]
}, {
"name": "deepak",
"Date": [{
"day": "2016-09-28",
"status": "P"
}, {
"day": "2016-09-27",
"status": "A"
}, {
"day": "2016-09-29",
"status": "A"
},
{
"day": "2016-09-26",
"status": "P"
},
]
}]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="Ctrl">
<table>
<tbody>
<tr>
<td>S.No.</td>
<td>NAME</td>
<td>26-9-2016</td>
<td>27-9-2016</td>
<td>28-9-2016</td>
<td>29-9-2016</td>
</tr>
<tr data-ng-repeat="student in students.def" st-select-row="row">
<td data-ng-bind="$index+1"></td>
<td data-ng-bind="student.name"></td>
<td data-ng-repeat="data in student.Date | orderBy :'day'" data-ng-bind="data.status"></td>
</tr>
</tbody>
</table>
</body>
The Json data has some keys with wrong names so from your question made a bit assumption and did changes in your HTML part.
<tr data-ng-repeat="student in students.def" st-select-row="row">
<td data-ng-bind="$index+1"></td>
<td data-ng-bind="student.name"></td>
<td data-ng-repeat="data in student.Date | orderBy :'day'" data-ng-bind="data.status"></td>
</tr>
Just use orderBy and provide the key to perform ordering in your case 'day'

How to filter set of items from list of items - AngularJS

I have two scope variables in angularJS. One storing "all the subcategories" and other storing "categories and their respective subcategories".
$scope.Categories = [
{
"subcategories": [
{
"scname": "Sugar",
"scid": "5"
},
{
"scname": "Salt",
"scid": "6"
},
{
"scname": "Jaggery",
"scid": "7"
}
],
"name": "Salt and Sugar",
"id": "1",
"image": "/images/salt_sugar.png"
},
{
"subcategories": [
{
"scname": "Tea",
"scid": "8"
},
{
"scname": "Coffee",
"scid": "9"
},
{
"scname": "Tea Bags",
"scid": "162"
}
],
"name": "Tea and Coffee",
"id": "2",
"image": "/images/tea_and_coffee.png"
}
]
$scope.subcategories = [
{
"name": "Sugar",
"id": "5"
},
{
"name": "Salt",
"id": "6"
},
{
"name": "Jaggery",
"id": "7"
},
{
"name": "Tea",
"id": "8"
},
{
"name": "Coffee",
"id": "9"
},
{
"name": "Tea Bags",
"id": "162"
}
]
On selecting a category i want to display mapped and unmapped subcategories with that particular category. First one is very easy. How to filter second one? for example -
on selecting "Tea and Coffee" unmapped categories should be - Sugar, salt, Jaggery
on selecting "Salt and Sugar" unmapped categories should be - Tea, Coffee, Tea Bags
This is how I am listing mapped categories:
<TR align="center">
<TD>
<select ng-options="c as c.name for c in Categories|orderBy:'name' " ng-model="selectedCategory" size="10"> </select>
</TD>
<TD>
<select ng-options="sc as sc.scname for sc in selectedCategory.subcategories|orderBy:'scname' " ng-model="SelectedMappedSubCategory" size="10"> </select>
</TD>
<TD>
<select ng-options="sc as sc.name for sc in SubCategories | orderBy:'name' | ???????" ng-model="SelectedUnMappedSubCategory" size="10"> </select>
</TD>
</tr>
What logic should I use in-place if ?????????
If I understood correctly, why not just filter it?
| filter: {scname: SelectedUnMappedSubCategory.scname}
EDIT:
I can see that you edited the code you originally posted. I think you can achieve what you are trying to do, by this:
| filter: {id: SelectedUnMappedSubCategory.scid}
Create a customized filter:
sampleApp.filter('filterSubcategories', function() {
return function(input, filterkey) {
var filtered = [];
if (filterkey) {
for (var i = 0; i < input.length; ++i) {
var item = input[i];
var found = false;
for (var j = 0; j < filterkey.length; ++j) {
if (item.id == filterkey[j].scid) {
found = true;
break;
}
}
if (!found){
filtered.push(item);
}
}
}
return filtered;
};
});
and use this like:
<TD>
<select ng-options="sc as sc.name for sc in SubCategories | filterSubcategories:selectedCategory.subcategories | orderBy:'name'" ng-model="SelectedUnMappedSubCategory" size="10"> </select>
</TD>

How to filter Array in array key-value in AngularJS

I've the following structure.
[
{
"Variants": [
{
"SellPrice": "75.00",
"VariantID": "10",
"VariantName": "1 L",
"InCart": "2",
"MRP": "115.00",
"VariantImagePath": "/images/ruchi/710_10.png"
},
{
"SellPrice": "410.00",
"VariantID": "113",
"VariantName": "5 L",
"InCart": "1",
"MRP": "485.00",
"VariantImagePath": "/images/ruchi/710_113.png"
},
{
"SellPrice": "1080.00",
"VariantID": "219",
"VariantName": "15L - Jar",
"InCart": "0",
"MRP": "1275.00",
"VariantImagePath": "/images/ruchi/710_219.png"
}
],
"SubCategoryID": "32",
"ProductImagePath": "/images/ruchi/710.png",
"SubCategoryName": "Soyabean Oil",
"BrandName": "Ruchi",
"ProductID": "710",
"BrandID": "117",
"ProductName": "Ruchi soya oil"
},
{
"Variants": [
{
"SellPrice": "58.00",
"VariantID": "23",
"VariantName": "900 GM",
"InCart": "1",
"MRP": "60.00",
"VariantImagePath": "/images/mtr/771_23.png"
}
],
"SubCategoryID": "110",
"ProductImagePath": "/images/mtr/771.png",
"SubCategoryName": "Vermicelli",
"BrandName": "MTR",
"ProductID": "771",
"BrandID": "167",
"ProductName": "Seviyan Vermicelli"
}
]
Want to filter all the data where Variants.InCart value is > 0.
In this case output will be
ProductID VariantID InCart
710 113 1
710 10 2
771 23 1
and this is my loop.
<tr ng-repeat="Item in ProductService.Products | <what should be filter condition here>">
<td>{{Item.ProductID}} {{Item.Variants.VariantID}} {{Item.Variants.InCart}}</td>
</tr>
Please help.
<tr ng-repeat="Item in ProductService.Products | filter:customArrayFilter">
<td>{{Item.ProductID}} {{Item.Variants.VariantID}} {{Item.Variants.InCart}}</td>
</tr>
$scope.customArrayFilter = function (item) {
return (item.InCart > 0);
};
You can add custom filter like this..

Resources