AngularJS - Summing filtered rows in table - angularjs

Based in this example I need to sum the ages of the filtered users. It means, if I have three names filtered, the filter in the controller must to sum only these the ages.
html
<div data-ng-app="app" data-ng-controller="controller">
<input type="text" data-ng-model="parameter" placeholder="search">
<p/>
<table border="1">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Age</th>
</tr>
<thead>
<tbody>
<tr data-ng-repeat="user in users | filter: parameter">
<td>{{$index+1}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total ages</td>
<td>{{users | sumByKey: 'age'}}</td>
</tr>
</tfoot>
</table>
</div>
angularjs
var app = angular.module("app", []);
app.filter('sumByKey', function() {
return function(data, key) {
if (typeof(data) === 'undefined' || typeof(key) === 'undefined') {
return 0;
}
var sum = 0;
for (var i = data.length - 1; i >= 0; i--) {
sum += parseInt(data[i][key]);
}
return sum;
};
});
Any idea?

You could store the filtered data in a filteredList and pass it for the calculation,
<tbody>
<tr data-ng-repeat="user in (filteredList = (users | filter: parameter))">
<td>{{$index+1}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total ages</td>
<td>{{filteredList | sumByKey: 'age' }}</td>
</tr>
</tfoot>
DEMO

Related

Angular 1.x - How to display table with dynamic rows and columns

Aim - Display a dynamic table for both rows and columns as below -
Dynamic Header - The fund codes are values for "name" from the json object array.
Dynamic rows with values for Application, Redemption and Net
JSON object :
[
{
name: 'VBIF',
application: 1000,
redemption: -200,
netAppRed: 800
},
{
name: 'VCIF',
application: 1500,
redemption: -200,
netAppRed: 800
},
{
name: 'VMPF',
application: 2000,
redemption: 0,
netAppRed: 2000
},
{
name: 'VBIF-A',
application: 800,
redemption: 100,
netAppRed: 700
},
{
name: 'VMPF-A',
application: 43540,
redemption: 12550,
netAppRed: 30990
}
]
HTML :
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Fund Code</th>
<th>Application</th>
<th>Redemption</th>
<th>Net Application Redemption</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="cashflow in cashflows">
<td>{{cashflow.name}}</td>
<td>{{cashflow.application | currency}}</td>
<td>{{cashflow.redemption | currency}}</td>
<td>{{cashflow.netAppRed | currency}}</td>
</tr>
</tbody>
</table>
</div>
Current view displays :
Another option without need to change model:
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Fund Code</th>
<th data-ng-repeat="cashflow in cashflows">{{cashflow.name}} </th>
</tr>
</thead>
<tbody>
<tr >
<td>Application</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.application | currency}}</td>
</tr>
<tr >
<td>Redemption</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.redemption | currency}}</td>
</tr>
<tr >
<td>NetAppRed</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.netAppRed | currency}}</td>
</tr>
</tbody>
</table>
</div>
Resovled it by changing the model in the controller as below -
$scope.getHeaders = function (){
var keys = [];
angular.forEach(object, function (val, key) {
if(key !== '$$hashKey') { keys.push(key); }
});
return keys;
};
$scope.getValue = function () {
var values = [];
angular.forEach(object, function (val, key) {
if(key !== '$$hashKey') { values.push(val); }
});
return values;
};
The HTML updated as below -
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th ng-repeat="(header, value) in cashflows">
{{value.name}}
</th>
</tr>
</thead>
<tbody>
<tr>
<td>Application</td>
<td ng-repeat="row in cashflows">
{{row.application}}
</td>
</tr>
<tr>
<td>Redemption</td>
<td ng-repeat="row in cashflows">
{{row.redemption}}
</td>
</tr>
<tr>
<td>Net App & Red</td>
<td ng-repeat="row in cashflows">
{{row.netAppRed}}
</td>
</tr>
</tbody>
</table>
</div>
Final Output :
you can use ng-tables to show your dynamic data
here is example
[https://www.tutlane.com/tutorial/angularjs/angularjs-tables-with-ng-table][1]
if any query ask me on comment

How to Sum From Multi object

Please help me, I'm using 2 JSON feed, need to display array value in one table then add sum row for each column, but I don't know how to call Expense Table and sum it.
Income JSON Table:
nominal_income
Expense JSON Table:
nominal_expense
If you have any example please let me know :D
My HTML:
<table ng-controller="incomeCtrl">
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td> // how to call this?
</tr>
<tr>
<td class="text-left" >{{ income_total | number:2 }}</td>
<td class="text-left" >{{ expense_total | number:2 }}</td> //how to sum this ?
</tr>
</table>
JS Controller:
$scope.runEvent = function(item) {
var income_total = 0;
angular.forEach(item, function(item) {
income_total = income_total -(- incomes.nominal_income)
;})
$scope.income_total = income_total;}
Use a custom function and call the function with key parameter
angular.module("test",[]).controller("testc",function($scope) {
$scope.incomes=[{nominal_income:20,nominal_expense:75.5},{nominal_income:30.00,nominal_expense:14.50},{nominal_income:49.99,nominal_expense:10}]
$scope.average = function(array, key) {
var value= 0,
average;
for (var i = 0; i < array.length; i++) {
value+= array[i][key];
}
return value;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="testc">
<table >
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td>
</tr>
<tr>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_income") | number:2 }}
</td>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_expense") | number:2 }}
</td>
</tr>
</table>
</div>
Update: How to join IncomeCtrl and ExpenseCtrl
You can call another controller inside a controller as nested controller. Or you can pass the data from one controller to another controller by using $routScope or $Cookies or $service or $BroadCase etc
<table ng-controller="incomeCtrl">
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td ng-controller="ExpenseCtrl" class="text-left">{{expenses[$index].nominal_expense}}</td> // may you need $$parent.$index
</tr>
<tr>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_income") | number:2 }}
</td>
<td ng-controller="ExpenseCtrl" style="color:green" class="text-left" >{{average(expenses,"nominal_expense") | number:2 }}
</td>
</tr>
</table>
You can pass a type / column as a parameter to be reduced to get the sum. Here is an example:
var app = angular.module('myApp', []);
app.controller('incomeCtrl', function($scope, incomeService) { // incomeService injected here as a serivce
var inc = incomeService.get_income();
var exp = incomeService.get_expense();
$scope.incomes = [];
/* works if `inc` and `exp` have the same length, merge with caution! */
for (var i = 0; i < inc.length; i++) {
$scope.incomes.push({
"nominal_income": inc[i],
"nominal_expense": exp[i]
})
}
$scope.sum = function(type) {
return $scope.incomes.reduce((x, y) => {
return x + y[type];
}, 0);
}
});
app.factory('incomeService', function() {
var service = {};
var data = {
"income": [2.01, 3.23, 6.56],
"expense": [1.12, 2.34, 5.67]
}
service.get_income = function() {
return data.income;
}
service.get_expense = function() {
return data.expense;
}
service.set_income = function(array) { // populated in incomeCtrl
data.income = array;
}
service.set_expense = function(array) { // populated in expenseCtrl
data.expense = array;
}
return service;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="incomeCtrl">
<table>
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td>
</tr>
<tr style="color:red;">
<td class="text-left">{{sum('nominal_income') | number:2}}</td>
<td class="text-left">{{sum('nominal_expense') | number:2}}</td>
</tr>
</table>
</div>

How to clone and print data in angular

I have a table which prints data from a JSON. Every row have an delete option.
I want to print the deleted data into a new table. I have managed to print data in console but unable to add it into view.
Below is the code:
Controller
$scope.deletedItems = [];
var counter = 0
$scope.removeRow = function (idx) {
console.log(idx);
$scope.TTNdata.splice(idx, 1);
var deletedArray = $scope.TTNdata.slice(idx, 1);
//console.log(deletedArray);
$scope.deletedItems.push(deletedArray);
console.log($scope.deletedItems);
counter++;
$('#counter').html(counter);
};
View:
<table id="deleted-rows" class="">
<thead>
<th>Sr. No</th>
<th>ID</th>
<th>First Name</th>
<th>Second Name</th>
<th>Gender</th>
<th>Email</th>
<th>Image</th>
<th>Remove</th>
</thead>
<tbody>
<tr ng-repeat="item in deletedItems | orderBy:'id'">
<td>{{$index+1}}</td>
<td>{{item.id}} </td>
<td>{{item.first_name}}</td>
<td>{{item.last_name}}</td>
<td>{{item.gender}}</td>
<td>{{item.email}}</td>
<td><img src="{{item.photo}}" alt="{{item.first_name}} {{item.last_name}} photo"></td>
<td class=""> <span style="cursor:pointer" ng-click="removeRow($index)" title="Remove Record" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
<table class="table bordered">
<thead>
<tr>
<th>Sr. No</th>
<th>ID</th>
<th>First Name</th>
<th>Second Name</th>
<th>Gender</th>
<th>Email</th>
<th>Image</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in TTNdata | filter:bindtext | orderBy:'id'">
<td>{{$index+1}}</td>
<td>{{data.id}} </td>
<td>{{data.first_name}}</td>
<td>{{data.last_name}}</td>
<td>{{data.gender}}</td>
<td>{{data.email}}</td>
<td><img src="{{data.photo}}" alt="{{data.first_name}} {{data.last_name}} photo"></td>
<td class=""> <span style="cursor:pointer" ng-click="removeRow($index)" title="Remove Record" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
Data is printing in console but not in table, every time i click remove it will generate a blank row in deleted table
What I am doing wrong?
Code on github https://github.com/sahilpopli/learningAngular.git
slice returns array, so try $scope.deletedItems.push(deletedArray[0]);
Or try to concatenate the arrays by doing so: $scope.deletedItems = $scope.deletedItems.concat(deletedArray);
A possible thing that you may need to think is that if you going to have paged tables, removing the object from a list with that index could not be a good thing.
My solution to your problem would be this(using the id instead of index). This is just scratch demonstrating a possible way to achieve what is your desire.
Code
angular.module('App', [])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.List = [{
Id: 1,
Name: 'Name1'
}, {
Id: 2,
Name: 'Name2'
}, {
Id: 3,
Name: 'Name3'
}];
$scope.newList = [];
var remove = function(itemId) {
var indexS = $scope.List.filter(function(item, index) {
return item.Id == itemId;
});
if (indexS.length == 1)
$scope.newList.push($scope.List.splice($scope.List.indexOf(indexS[0]), 1)[0])
};
$scope.removeMe = remove;
}]);
Markup
<body ng-app="App" ng-controller="MyCtrl">
<table>
<thead>
<th> Id </th>
<th> Name </th>
</thead>
<tbody>
<tr ng-repeat="item in List">
<td >{{item.Id}}</td>
<td >{{item.Name}}</td>
<td ng-click="removeMe(item.Id)">removeme</td>
</tr>
</tbody>
</table>
<table>
<thead>
<th> Id </th>
<th> Name </th>
</thead>
<tbody>
<tr ng-repeat="item in newList">
<td >{{item.Id}}</td>
<td >{{item.Name}}</td>
</tr>
</tbody>
</table>
Plunker

Get total td values with Angular JS

I'm trying to add total price with using Angular JS.
<table>
<tr>
<th>Price</th>
</tr>
<tr>
<td>10</td>
</tr>
<tr>
<td>20</td>
</tr>
<tr>
<td>30</td>
</tr>
<tr>
<td>40</td>
</tr>
<tr>
<td>50</td>
</tr>
<tr>
<td>Total Price</td>
</tr>
</table>
This is a possible way of achieving what you asked for using ng-init:
<table ng-init="items.total = {}">
<tr>
<td>name</td>
<td>numberofyears</td>
<td>amount</td>
<td>intrest</td>
</tr>
<tr ng-repeat="item in items">
<td>{{item.name}}</td>
<td ng-init="items.total.numberofyears = items.total.numberofyears + item.numberofyears">{{item.numberofyears}}</td>
<td ng-init="items.total.amount = items.total.amount + item.amount">{{item.amount}}</td>
<td ng-init="items.total.interest = items.total.interest + item.interest">{{item.interest}}%</td>
</tr>
<tr>
<td>Total</td>
<td>{{items.total.numberofyears}}</td>
<td>{{items.total.amount}}</td>
<td>{{items.total.interest}}%</td>
</tr>
</table>
Do something like this:
HTML:
<table>
<tr ng-repeat = "price in prices">
<td ng-bind="price.price"><td>
</tr>
<tr>
<td ng-bind="calculateTotal()"><td>
</tr>
</table>
JS:
$scope.prices = [{
"price": "5"
}, {
"price": "10"
}, {
"price": "13"
}];
$scope.calculateTotal = function() {
var total = 0;
for (i = 0; i < $scope.prices.length; i++) {
total += +$scope.prices[i].price; // (+) sign before variable is used to convert string values to number
}
return total;
};

Clear css class on table row pagination

I got a smart-table with pagination. I have a controller that apply a css class to the selected row. So the issue is that it keeps the selection on the index on other pages, so I'm searching for a way to clear the class when I use or click pagination.
This is the table:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="TestCtrl">
<div class="smart-table-container">
<table id="mytable" st-safe-src="dataSet" st-table="displayed" class="smart-table table">
<thead>
<tr >
<th >A COLUMN</th>
<th >A COLUMN</th>
<th >A COLUMN</th>
<th >A COLUMN</th>
<th >A COLUMN</th>
</tr>
</thead>
<tbody data-ng-dblclick="scrollTo()">
<tr data-ng-repeat="row in displayed" st-select-row="row" st-select-mode="single" data-ng-click="$parent.setClickedRow($index)" and data-ng-class="{'selected':$index == $parent.selectedRow}">
<td data-ng-click="$parent.selData(row);">{{$index}}</td>
<td data-ng-click="$parent.selData(row);">{{row.asd}}</td>
<td data-ng-click="$parent.selData(row);">{{row.dsa}}</td>
<td data-ng-click="$parent.selData(row);">{{row.qwe}}</td>
<td data-ng-click="$parent.selData(row);">{{row.ewq}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="text-center" st-pagination="" st-items-by-page="5" colspan="8">
</td>
</tr>
</tfoot>
</table>
</div>
</div>
And this is the code related to the selection:
angular.module('myApp', []);
function TestCtrl($scope) {
$scope.selectedRow = null;
$scope.displayed = [{asd:3},{asd:3},{asd:3},{asd:3},{asd:3},{asd:3}]
$scope.setClickedRow = function(index){
$scope.selectedRow = index;
}
}
And the css class:
.selected {
background-color: #67BBED;
}
Including this in your controller may work
$scope.$watch('displayed', function() {
$scope.selectedRow = null;
});
http://plnkr.co/edit/hX093vHZkoZSPvfRnqJE?p=preview

Resources