Calculate the Sum of Values using ng-repeat in Angular js - angularjs

I am newbie to Angular js.I am just trying to calculate the sum of Values of each row using angular js.Here, I am dynamically adding and removing rows.
For Eg: Let's say first row value is 30, Now I added one row with value 30, then total should be show 60 like this.
1. 30
2. 30
3. 50
Total 120
HTML Code:
<table id="t1" style="border:none;">
<tr><th>Start</th><th>Stop</th><th>Downtime(In Min)</th><th>Reason</th></tr>
<tr ng-repeat="item in invoice">
<td><input type="text" required ng-model="$invoice.start" name="r1[]"></td>
<td><input type="text" required ng-model="$invoice.stop" name="r2[]" ng-blur="diff($invoice)"></td>
<td><input type="text" name="r3[]" ng-model="$invoice.diff"/></td>
<td style="border:none;"><a href ng-click="remove(item)">X</a></td>
</tr>
<tr style="border:none;">
<td style="border:none;"><a href ng-click="add()">+</a></td>
</tr>
</table>
<span class="labelCode">Total Downtime</span><input required type="text" name="Tot_D" ng-value="d1()"/></span></br>
Angular JS:
$scope.d1=function(){
var total = 0;
for(var i = 0; i < $scope.invoice.length; i++){
var product = $scope.invoice[i];
total += parseInt(product.diff);
}
return total;
}
//Calculate the Difference between two times
$scope.diff = function(item) {
item.diff = computeDiff(item.start,item.stop);
}
function computeDiff(start, stop) {
if (start && stop) {
var s_hr = start.split(":")[0];
var s_min = start.split(":")[1];
var e_hr = stop.split(":")[0];
var e_min = stop.split(":")[1];
return Math.abs((parseInt(e_hr) - parseInt(s_hr)) * 60) + Math.abs(parseInt(e_min) - parseInt(s_min))
}
}
Now, it just showing NaN. I don't know what is wrong.
Please help out.Thanks in advance.

Related

Checkbox checked not updating on delete, its updating the second time

i have a code like this:
<body ng-app="UserManagement" ng-controller="UserManagementController">
<h3>to do</h3>
<form ng-submit="addtodo();">
<table>
<tr><td colspan="2"><input type="checkbox" ng-model="employees.todo" /></td></tr>
<tr><td colspan="2">{{remng()}} of {{actuallength}} remaining</td></tr>
<tr ng-repeat="emp in employees">
<td><input type="checkbox" ng-model="emp.todo" /></td>
<td>{{emp.name}}</td>
</tr>
<tr>
<td><input type="text" ng-model="addemp" /></td>
<td><input type="button" value="Add" ng-click="addemps()"/></td>
</tr>
<tr>
<td><input type="button" value="Delete" ng-click="deleteemps();"/></td>
</tr>
</table>
</form>
</body>
here i am making simple add, delete operation of a list of employees. In the delete operation, when i click delete without checking any checkbox, the items with existing checked checkboxes are deleted, but when i click any checkbox and press delete, the clicked checkbox is not deleted this time, but when i click delete second time, it deletes.
Js code:
var app = angular.module("UserManagement", []);
//Controller Part
app.controller("UserManagementController", function($scope, $http) {
$scope.employees = [
{name:'Abhinav',todo:true},
{name:'Amit', todo:false},
{name:'Raghav',todo:true},
{name:'Sumit', todo:false},
{name:'Ashwani',todo:true},
{name:'Mihir', todo:false},
]
$scope.totalsel = $scope.employees.length;
$scope.actuallength = $scope.totalsel;
alert($scope.actuallength);
//$scope.addtodo = function(){}
//alert("ddd");
$scope.deleteemps = function(){
//alert($scope.employees.name);
$scope.deleted_emps = [];
//alert("in foreach: "+$scope.employees[2].todo);
angular.forEach($scope.employees, function(todos, index) {
//alert(todos.todo);
//alert(todos.name);
if(todos.todo){
// alert(index)
var deletednames = todos.name;
// var deletedtodo = todos.todo;
//$scope.deleted_emps.push(deletednames)
// alert(deletednames);
$scope.deleted_emps.push({name:todos.name, todo:todos.todo});
//var abc=angular.toJson($scope.deleted_emps);
// alert(index);
//console.log(angular.toJson(todos.name));
console.log("hiii: "+$scope.deleted_emps.name);
var indx;
for (var i=0; i<$scope.deleted_emps.length; i++) {
console.log("iii: "+$scope.deleted_emps[i].name);
console.log("i: "+$scope.employees[index].name);
//console.log($scope.employees[index].name.indexOf($scope.deleted_emps[i].name));
indx = $scope.employees[index].name.indexOf($scope.deleted_emps[i].name);
// alert(indx);
if (indx > -1) {
// alert(indx);
//$scope.employees.splice()
$scope.employees.splice(index, 1);
}
}
/* var indx;
for (var i=0; i<array2.$scope.deleted_emp; i++) {
indx = array1.indexOf(array2[i]);
if (indx > -1) {
array1.splice(indx, 1);
}
}
*/
}
$scope.actuallength = $scope.totalsel;
})
}
});
I am using angular js 1.6.1 . Thanks in advance.
I've made a fiddle based on your codes.
Add and Delete Employees
Sample code of mine is like this.
$scope.deleteEmp = function(){
var slicedEmps = [];
angular.forEach($scope.employees, function(e){
if(!e.isChecked){
slicedEmps.push(e);
}
});
$scope.employees = slicedEmps;
};
What I suggested is making new array instead of using 'splice'.
I hope this fiddle can help you. :)

Sum of ng model not working in ng repeat

HTML
<tr ng-repeat-start="marks in pagedItemss">
<td>
<input type="text" ng-model="marks.aaa" ng-pattern="/^[0-9]*$/" maxlength="3">
</td>
<td>
<input type="text" ng-model="marks.bbb" ng-pattern="/^[0-9]*$/" maxlength="3">
</td>
<td>
<span ng-model="sum" ng-bind="calculateSum()"></span>{{sum ? sum : 0}}
</td>
</tr>
CONTROLLER
$scope.calculateSum = function () {
var sum = 0;
for (var i = 0;i<$scope.pagedItemss.length;i++)
{
sum += $scope.pagedItemss[i]["aaa"]+$scope.pagedItemss[i]["bbb"];
}
$scope.sum=sum;
return sum;
}
Sum of ng-model not working. I given values as (aaa:25,bbb:30), but it showing side by side values like 02530.
You need to convert string values to integers before adding.
Ex:
var a = "20", b="30";
var c = a+b
// c will be 2030
To get correct values parseInt() both values before adding.
var c = parseInt(a)+parseInt(b);
// c will be 50
When you are taking the value of an input element with type="text", the value will be a String.
In JS, the + operator concatenates the strings:
0 + '25' + '30' = '02530'
One possible fix would be to change the input boxes to type number:
<input type="number" ...>
Alternatively you could convert the text values to a Number before you operate on them (there are many ways to do this is JS):
$scope.calculateSum = function () {
var sum = 0;
for (var i = 0;i<$scope.pagedItemss.length;i++)
{
sum += Number($scope.pagedItemss[i]["aaa"])+Number($scope.pagedItemss[i]["bbb"]);
}
$scope.sum=sum;
return sum;
}

How to calculate the sum of repeated elements in AngularJS?

I am new to AngularJS and stuck on a problem from last one week.
I am getting dynamic weekly values for different groups.
My target is to caculate the sum of values for each group which is doable through filter, but I am not able to figure out how to re-calulate the weeklyvalues if I change the value of sum. What I have done so far:
Controller:
app.controller("CalculationController", [
"$scope", "calculationService", function ($scope, calculationService) {
getGroups();
function getGroups() {
calculationService.GetGroups().success(function(groups) {
$scope.groups= groups;
console.log(groups);
}).error(function (error) {
$scope.status = "Error Occured: " + error.message;
console.log($scope.status);
});
}$scope.getTotal = function () {
var groupTotal = [];
var total = 0; // hold the total for week
var totalPerGroup = 0;
var totalPerGroupArr = [[], []]; //array to store total values Per Group
var groups = $scope.groups; //getting the data of groups in a variable.
var totalCostForEachWeekPerMainGroup = [[], []]; //array to store total groups for each week
var totalGroupsCostPerGroup = []; //array to store the total cost per group
totalCostPerMainGroup = 0; //sum of all groups per Main Group
for (var i = 0; i < trps.length; i++) {
total = 0;
totalPerGroup = 0;
for (var j = 0; j < groups[i].WeeklyValues.length; j++) {
totalCostForEachWeekPerMainGroup[j][i] = groups[j].WeeklyValues[i].Cost;
totalPerGroupArr[i][j] = groups[i].WeeklyValues[j].Cost;
totalPerGroup += totalPerGroupArr[i][j];
total += totalCostForEachWeekPerMainGroup[j][i];
totalCostPerMainGroup += totalCostForEachWeekPerMainGroup[j][i];
}
groupTotal.push(total);
totalGroupsCostPerGroup.push(totalPerGroup);
$scope.totalGroupsCostPerMainGroup = totalCostPerMainGroup;
}
//Percentage calculation for each week
return groupTotal;
}
}]).filter('sumCalculation', function () {
return function (data, key) {
if (typeof (data) === 'undefined' || typeof (key) === 'undefined') {
return 0;
}
var total = 0;
for (var i = 0; i < data.length; i++) {
total += parseFloat(data[i][key]);
}
//$scope.sum = total;
return total;
}});
View:
<table class="table table-hover">
<tr>
<th>#Html.Label("Main Group")</th>
<th>#Html.Label("Group")</th>
<th ng-repeat="w in numberOfWeeks" ng-cloak>W{{w}}-2016</th>
<th>#Html.Label("Total")</th>
</tr>
<tr ng-repeat="(k, v) in GroupTotalPerMainGroupPerWeek"> // coming from another service
<td>{{k}}</td>
<td></td>
<td></td>
<td ng-repeat="cost in getTotal()">
{{cost}}
</td>
<td>{{totalGroupsCostPerMainGroup}}</td>
</tr>
<tr ng-repeat="g in groups">
<td></td>
<td ng-cloak>{{g.GroupName}}</td>
<td ng-repeat="c in g.WeeklyValues">
<input value="{{c.Cost}}" class="form-control" type="number" ng-model="c.Cost" ng-cloak/>
</td>
<td>
<input value="{{g.WeeklyValues|sumCalculation:'Cost'}}" class="form-control" string-to-number ng-model="Cost" type="number" ng-cloak/>
</td>
</tr>
</table>
Service:
app.factory("CalculationService", ['$http', function ($http) {
var CalculationService= {};
CalculationService.GetGroups = function () {
return $http.get("/Angular/GetGroups");
}
return CalculationService;}]);
What I want to achieve:
Calculate the sum of each value per group
Calculate the sum of all groups per week
Calculate the total sum of all groups
If i change the value of sum it should change the each weekly value accordingly
If i change the value of total (i.e. 1265 in example) it should recalculate the sum (value) of each group and each weekly value should be re-calculated:
The example of view is like:
GroupName------Week1Value------Week2Value------Week3Value------Sum
------------------ 312 ------------- 328 --------- 625----------- 1265
G1-------------- 112 ------------- 113 --------- 300 ---------- 525
G2-------------- 200 ------------- 215 --------- 325 ---------- 740

How to create table headers in a dynamically sized table using Angularjs

I want to create a dynamic height & width table, but I'm having trouble with the table header.
The <td> elements display just fine with this ng-repeater
<tr ng-repeat="set in currFormData.volume track by $index">
<td ng-repeat="repSpace in set track by $index">
{{repSpace}}
</td>
</tr>
but I want a <th> row containing 1, 2, 3, 4... and it must adjust as the table adjusts. I'm looking for something like this which looks through only the second level of my model 1 time:
<tr>
<th ng-repeat="repSpace in set in currFormData.volume track by $index">{{$index + 1}}</th>
</tr>
Here is my $scope model:
$scope.currFormData = {"date" : "", "volume": [
[[1,135],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],
[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],
[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],
[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]
] };
How can I make this work? I'm open to changing my model.
Assuming that every 'set' in your 'volume' will be of equal length:
HTML:
<th ng-repeat="i in getArray(currFormData.volume[0].length) track by $index">{{$index + 1}}</th>
Controller:
$scope.getArray = function (length) {
return new Array(length);
}
Otherwise:
HTML:
<th ng-repeat="i in getLongestArray(currFormData.volume) track by $index">{{$index + 1}}</th>
Controller:
$scope.getLongestArray = function (arrayOfArrays) {
var longest: number = 0;
for (var i: number = 0; i < arrayOfArrays.length; i++) {
if (arrayOfArrays[i].length > longest) {
longest = arrayOfArrays[i].length;
}
}
return (new Array(longest));
}

AngularJs ng-repeat change loop increment

I'm newbie to AngularJs. I want to use ng-repeat as for(i=0; i < ele.length; i+=2)
I have a table with 4 columns, where I'm going to use ng-repeat
<table>
<tr ng-repeat="i in elements">
<th>{{i.T}}</th>
<td>{{i.V}}</td>
<th>{{elements[($index+1)].T}}</th> <!-- This should be next element of the elements array -->
<td>{{elements[($index+1)].V}}</td> <!-- This should be next element of the elements array -->
</tr>
</table>
I need to access 2 elements in a single iteration and iteration increment should be 2
I hope this make sense. Please help me.
Please check this html view Plunker
You can create a filter that creates an even copy of the array:
.filter("myFilter", function(){
return function(input, test){
var newArray = [];
for(var x = 0; x < input.length; x+=2){
newArray.push(input[x]);
}
return newArray;
}
});
JsFiddle: http://jsfiddle.net/gwfPh/15/
So if I understand correctly you want to walk your list and alternate th and td's while iterating.
If so you could use a ng-switch:
<table>
<tr ng-repeat="i in elements" ng-switch on="$index % 2">
<th ng-switch-when="0">{{i.T}}</th>
<td ng-switch-when="1">{{i.V}}</td>
</tr>
</table>
See Plunker here
One solution I can think of involves a change in the data model
Template
<table ng-app="test-app" ng-controller="TestCtrl">
<tr ng-repeat="i in items">
<th>{{i.T1}}</th>
<td>{{i.V1}}</td>
<th>{{i.T2}}</th>
<td>{{i.V2}}</td>
</tr>
</table>
Controller
testApp.controller('TestCtrl', ['$scope', function($scope) {
var elements=[]; //This is the dynamic values loaded from server
for (var i = 0; i < 5; i++) {
elements.push({
T : i,
V : 'v' + i
});
}
//A converter which convert the data elements to a format we can use
var items = [];
var x = Math.ceil(elements.length / 2);
for (var i = 0; i < x; i++) {
var index = i * 2;
var obj = {
T1 : elements[index].T,
V1 : elements[index].V
}
if (elements[index + 1]) {
obj.T2 = elements[index + 1].T;
obj.V2 = elements[index + 1].V
}
items.push(obj)
}
$scope.items = items;
}]);
Demo: Fiddle
Another slightly different approach can be found here.

Resources