sum of the items of a nested ng-repeat [duplicate] - javascript

This question already has answers here:
Calculating sum of repeated elements in AngularJS ng-repeat
(20 answers)
Closed 5 years ago.
I am trying to do some calculations inside ng-repeat where i want to get the total price out from each nested ng-repeat from the list.
<div class="Container" ng-repeat="items in list">
<div class="top">i am in the top {{items.date}}</div>
<div class="item" ng-repeat="item in items">
<a>{{item.count}}</a>
<a ng-init="setTotals(total = (item.count * item.price))">{{item.price}}</a>
</div>
<div class=bottom">total price: {{totalPrice}}</div>
</div>
this is the angular scope i try to get:
$scope.setTotals = function (total) {
$scope.totalPrice = total * total;
}
but this just doubles the output of a single item, how would i be able to get the total amount of all the items in the nested ng-repeat?

Assuming the list of items is like:
$scope.list = [
{date: '2017-12-14', items: [
{count: 3, price: 9},
{count: 1, price: 20}
]},
{date: '2017-12-15', items: [
{count: 2, price: 10},
{count: 5, price: 20}
]}
];
And that you want to calculate sum of prices per day with function:
$scope.calculateTotal = function (dayItems) {
let total = 0;
for (item of dayItems.items) {
total += (item.count * item.price);
};
return total;
}
The html becomes like:
<div class="Container" ng-repeat="items in list">
<div class="top">i am in the top {{items.date}}</div>
<div class="item" ng-repeat="item in items.items">
<a>{{item.count}}</a>
<a>{{item.price}}</a>
</div>
<div class=bottom">total price: {{calculateTotal(items)}}</div>
</div>
See working demo plunker. Of course you can modify code to fit your needs, it is only a sample implementation.

Add function to controller:
$scope.getTotalPrice = function(items)
{
return items.reduce(function(sum, item)
{
return (sum + (item.count * item.price));
}, 0);
};
call it in html:
<div class="Container" ng-repeat="items in list">
<div class="top">i am in the top {{items.date}}</div>
<div class="item" ng-repeat="item in items">
<a>{{item.count}}</a>
<a>{{item.price}}</a>
</div>
<div class=bottom">total price: {{ getTotalPrice(items) }}</div>
</div>

What you can do here is to do the calculation logic in your controller and just display its result in your view:
JavaScript:
$scope.totalPrice = $scope.items..reduce((sum, item) => {
return (sum + item.count * item.price);
}, 0);
HTML:
<div class="Container" ng-repeat="items in list">
<div class="top">i am in the top {{items.date}}</div>
<div class="item" ng-repeat="item in items">
<a>{{item.count}}</a>
<a>{{item.price}}</a>
</div>
<div class=bottom ">total price: {{totalPrice}}</div>
</div>

Related

How to create new bootstrap row per two items on Angular?

I'd like to add row on each 2 elements of ngFor loop.But I couldnt handle it.
I have studentNames array like below
studentNames=[
{
name:"Jonas",
age:22,
number:"1234"
},
{
name:"Mathilda",
age:25,
number:"5432"
},
{
name:"Jacob",
age:20,
number:"4321"
},
{
name:"Ivan",
age:23,
number:"6984"
},
{
name:"Kate",
age:21,
number:"3432"
},
{
name:"James",
age:20,
number:"4312"
},
{
name:"Sean",
age:23,
number:"4321"
},
{
name:"Julia",
age:23,
number:"4321"
},
]
Here what I tried
<ng-container *ngFor="let item of studentNames;let i=index">
<div class="row" *ngIf="i%2==0">
<div class="col md-12">
{{item.name}}
</div>
</div>
</ng-container>
This only skipped when index is not even.
Here how I want to see them below(order doesnt matter only should be 2 by 2 per row).
Stackblitz example: https://stackblitz.com/edit/bootstrap-wpfukz?file=app%2Fapp.component.html
This is a bit more "hacky" approach but it's HTML-only:
<ng-container *ngFor="let item of studentNames;let i=index">
<div *ngIf="i%2==0">
<div class="row">
<div class="col md-12">
{{studentNames[i].name}}
</div>
<div class="col md-12">
{{studentNames[i + 1].name}}
</div>
</div>
</div>
</ng-container>
You can try like below. Use *ngFor exported value index and use half length of the array to continue the loop
<ng-container *ngFor="let item of studentNames; let j = index;">
<ng-container *ngIf="j < (studentNames.length / 2)">
<div class="row">
<div class="col md-6">
{{item.name}}
</div>
<div class="col md-6">
{{ studentNames[ j + (studentNames.length / 2) ].name }}
</div>
</div>
</ng-container>
</ng-container>
Working stackblitz
Note : Array length should be an even number ;)

Separate category item angularJS

How to list items in AngularJS and separate them by category, something like this:
<h3>Products</h3>
<div ng-repeat="item in products">
<div>
{{item.category}}
</div>
<p>
{{item.name}}
</p>
<p>
{{item.price}}
</p>
</div>
$scope:
$scope.products = [
{
name:"product1",
price:"450",
category:"cat1"
},
{
name:"product2",
price:"450",
category:"cat2"
},
{
name:"product3",
price:"450",
category:"cat1"
}
];
I want it to look something like this:
cat1
--->product1
--->product3
cat2
--->product2
...
Please help!
See [fiddle])(http://jsfiddle.net/Lvc0u55v/2846/)
I did some formatting to message the data in desired format.
$scope.productCategories = {};
for (var i = 0; i < products.length; i++) {
if ($scope.productCategories[products[i].category] == undefined)
$scope.productCategories[products[i].category] = [];
$scope.productCategories[products[i].category].push({
name: products[i].name,
price: products[i].price
});
}
Html Formatting is off, but I hope this gives you an idea
you can use groupBy filter in ng-repeat. you should add groupBy filter dependency in your app.
var app = angular.module("app",['angular.filter']);
app.controller("ctrl" , function($scope){
$scope.products = [ { name:"product1", price:"450", category:"cat1" }, { name:"product2", price:"450", category:"cat2" }, { name:"product3", price:"450", category:"cat1" } ];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>
<div ng-app="app" ng-controller="ctrl" class="panel-group" id="accordion">
<h3>Products</h3>
<div ng-repeat="(key,value) in products | groupBy: 'category'">
<div>
{{key}}
</div>
<div ng-repeat="item in value">
<p>
{{item.name}}
</p>
<p>
{{item.price}}
</p>
</div>
</div>
</div>

Strange behaviour when Ordering by dynamic count AngularJS -

I want to order this list of exercises by count, this works on first load, but when you start to click the increase or decrease, it increases/decreases the count of other indexes
HTML:
<div class="row" ng-repeat="exercise in exercises | orderBy:'count' ">
<div class="exercise-icon col-xs-2"> <img ng-src="{{ exercise.icon }}" /></div>
<div class="col-xs-6">
<p class="exercise-name"> {{ exercise.name }} </p>
</div>
<div class="col-xs-4 counters">
<span class="decrease" ng-click="decrease($index)">-</span>
<span class="count">{{ exercise.count }} </span>
<span class="increase" ng-click="increase($index)">+</span>
</div>
</div>
JS - Controller
app.controller('MainController', ['$scope', function($scope) {
$scope.exercises = [
{
icon: 'img/pushup.jpg',
name: 'Pushups',
count: 20
},
{
icon: 'img/squat.jpg',
name: 'Squats',
count: 15
},
{
icon: 'img/pullup.jpg',
name: 'Pullups',
count: 10
},
...
$scope.increase = function(index) {
$scope.exercises[index].count += 1;
};
$scope.decrease = function(index) {
if ( ($scope.exercises[index].count) > 0){
$scope.exercises[index].count -= 1;
}
};
Instead using $index pass object itself
Like this
<span class="decrease" ng-click="decrease(exercise)">-</span>
JS
$scope.decrease=function(exercise){
exercise.count--;
}

Using another scope object values within the ng-repeat of some other scope object

I have set up a fiddle to explain my question well. I would like to display the names from the $scope.gem inside ng-repeat [only one name for each ng-repeat and don't loop all] of $scope.knobItems without extending the knobItems scope. I want this to be made possible by maintaining the exact structure of controller as it is now. I am new to angular. I just wanna know if this is possible in angular and if is a good practice.
view
<div ng-app="myapp">
<div ng-controller="Mycont">
<div ng-repeat="knobs in knobItems">
<div ng-repeat="(key, value) in knobItems.nums">{{value.knobTitle}} : {{value.knobColor}}
<div ng-bind="gem[0].name"></div>
</div>
</div>
</div>
</div>
controller
var ngMod = angular.module("myapp", []);
ngMod.controller("Mycont", function ($scope) {
$scope.knobItems = {};
$scope.knobItems.nums = [{
knobTitle: "Company Profile",
knobColor: "#f46607"
}, {
knobTitle: "Deals left This Month",
knobColor: "#ffcc00"
}, {
knobTitle: "Pricelist",
knobColor: "#f40787"
}, {
knobTitle: "Pictures",
knobColor: "#a1b80a"
}, {
knobTitle: "Videos",
knobColor: "#14b9d6"
}];
$scope.gem = [{
name: "Thomas"
}, {
name: "Sebastian"
}, {
name: "June"
}, {
name: "Yuvan"
}];
});
intended output
Easy fix: fiddle
<div ng-app="myapp">
<div ng-controller="Mycont">
<div ng-repeat="knobs in knobItems">
<div ng-repeat="(key, value) in knobItems.nums">{{value.knobTitle}} : {{value.knobColor}}
<div ng-bind="gem[$index].name"></div>
</div>
</div>
</div>
</div>
The output in you fiddle is exactly the same without the first ng-repeat: http://jsfiddle.net/2nrbrfxL/
Going by you description rather than you code:
<div ng-app="myapp">
<div ng-controller="Mycont">
<div ng-repeat="knobs in knobItems">
<div ng-repeat="(key, value) in knobs">{{value.knobTitle}} : {{value.knobColor}}
<div ng-repeat="gemItem in gem">{{gemItem.name}}</div>
</div>
</div>
</div>
</div>
http://jsfiddle.net/p2fuq2du/
<div ng-app="myapp">
<div ng-controller="Mycont">
<div ng-repeat="(key, value) in knobItems.nums">{{value.knobTitle}} : {{value.knobColor}}
<div ng-bind="gem[key].name"></div>
</div>
</div>
</div>

multidimensional array in angular

I have a multidimensional array from an API. Is it possible to programatically loop through the array?
{
success: true,
categories: [{
cat_id: "2",
name: "This is category One",
description: null,
photo_url: "/img/test.png",
order: "1",
items: [{
item_id: "1",
title: "Desk",
item_url: "/690928460",
photo_url: "/desk.png",
}, {
item_id: "2",
title: "Chair",
item_url: "/18882823",
photo_url: "/chair.png",
},
}]
}]
}
My controller looks like this:
myApp.controller('items', function($scope, $http, $location, Data) {
var apiUrl = '/api/items';
$http.get(apiUrl).
success(function(data) {
$scope.data = Data;
$scope.allData = data;
});
$scope.changeView = function(view) {
$location.path(view);
}
});
Angular index file just has: <div ng-view=""></div>
View file
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="row" ng-repeat="categories in allData">
<div class="col-xs-6" ng-repeat="category in categories">
<div class="items">
<div class="title">
{{ category.name }}
</div>
</div>
</div>
</div>
</div>
</div>
I can loop through the category names fine, but when trying to return items for EACH category I don't understand the logic behind it...
I would suggest some simple nested for loops, as for each gives rise to more complexity.
As I'm not sure what you want to do with the data let's just create an array of all item names and one of all category names:
Within your success function:
var items = [], categories = []
for(var i = 0; i < data.categories.length;i++){
categories.push(data.categories[i].name);
for(var j = 0; j < data.categories[i].items.length;j++){
items.push(data.categories[i].items[j].name);
}
}
console.log(categories);
console.log(items);
EDIT:
Completely missed your html code somehow, here is my solution:
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="col-xs-6" ng-repeat="category in allData.categories">
<div class="items">
<div class="title">
{{ category.name }}
</div>
</div>
</div>
</div>
</div>
EDIT 2:
As to your comment:
If you want to select the secondary view's contents(ie the items) based on the selection of a category I would suggest a ng-click attribute. A directive could be used but isn't necessary:
<div class="scrollable categories-container animated-fast slideInUp">
<div class="container categories">
<div class="col-xs-6" ng-repeat="category in allData.categories">
<div class="title" ng_click="selected_category = category">
{{ category.name }}
</div>
</div>
<div class="col-xs-6" ng-repeat="item in selected_category.items">
<div class="title">
{{ item.name }}
</div>
</div>
</div>
</div>
So when your categories data is loaded the first ng-repeat is populated with the categories. Each div with class title will have a function called on click which will make the selected_category object equal the selected category.
This will then cause the second view to be populated with all the items in the selected category by Angular's two way bind.

Categories

Resources