I want to calculate a total of ng-repeat - angularjs

I want to calculate a total of amount of ng-repeat with the condition.
My table looks like this
<tr ng-repeat="Company in Companies track by $index">
<td>Departmend</td>
<td>Amount</td>
</tr>
<tr>
<td>HR</td>
<td>500</td>
</tr>
<tr>
<td>IT</td>
<td>200</td>
</tr>
<tr>
<td>HR</td>
<td>600</td>
</tr>
<tr>
<td colspan="2">Total:</td>
</tr>
My script like this.
<script>
if ($scope.Department == "HR") {
var Total = 0;
angular.forEach($scope.Companies, function (item) {
Total = Math.abs(Total) + Math.abs(item.Amount);
});
}
</script>

Are you looking for a solution like this? Finding the total of the array depending on its type?
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.Companies = [
{ Amount: 200, Department: "HR" },
{ Amount: 300, Department: "IT" },
{ Amount: 400, Department: "HR" },
{ Amount: 500, Department: "IT" },
{ Amount: 600, Department: "HR" }
];
$scope.totalValue = 0;
angular.forEach($scope.Companies, function(item) {
if (item.Department === "HR") {
$scope.totalValue += Math.abs(item.Amount);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<table>
<tr>
<td>Departmend</td>
<td>Amount</td>
</tr>
<tr ng-repeat="Company in Companies track by $index">
<td>{{Company.Department}}</td>
<td>{{Company.Amount}}</td>
</tr>
<tr>
<td>Total</td>
<td>{{totalValue}}</td>
</tr>
</table>
</body>

Related

ng-repeat over an array of objects (using ng-start)

I have an array of objects that I am trying to display. The problem is that I can only access the data by calling it by it's property name. I would like to be to iterate through using the object's key.
The object has two properties and each property represents a start time and an end time. They're to be displayed in each cell.
My table is structured like this:
<table class="table table-striped">
<tr>
<th></th>
<th ng-repeat="department in departments" style="vertical-align:top" colspan="2">{{department}}</th>
</tr>
<tr ng-repeat="time in times">
<td>{{weekdays[$index]}}</td>
<td ng-repeat-start="dept in time">{{times[$index].service.start}}</td>
<td ng-repeat-end>{{times[$index].service.end}}</td>
</tr>
</table>
In this case, how can I dynamically access the object?
My controller:
.controller("businessHours", function($scope) {
$scope.weekdays = ["Sunday", "Monday", "Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
$scope.departments = ["sales", "service","accounting","bodyshop","other","parts"];
$scope.times = [];
$.each($scope.weekdays, function(index, value) {
var dayTimes = {};
$.each($scope.departments, function(index2, value){
console.log(index)
dayTimes[value] = {start: '5', end: '6'};
});
$scope.times.push(dayTimes);
});
})
Am I going about this correctly or is there a better way to arrange my data structure?
Iterate over the (key,value) in ng-repeat in angular:
Read more about ng-repeat:
<div ng-repeat="(key, value) in myObj"> ... </div>,
In your case, update your html where:
<td ng-repeat-start="(key,dept) in time">{{times[$index][key].start}}</td>
<td ng-repeat-end>{{times[$index][key].end}}</td>
angular.module('app', [])
.controller('homeCtrl', function($scope) {
$scope.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
$scope.departments = ["sales", "service", "accounting", "bodyshop", "other", "parts"];
$scope.times = [];
angular.forEach($scope.weekdays, function(v, i) {
var dayTimes = {};
angular.forEach($scope.departments, function(value, index) {
console.log(index)
dayTimes[value] = {
start: '5',
end: '6'
};
});
$scope.times.push(dayTimes);
});
console.info($scope.times);
});
td,tr {
text-align:center;
min-width: 20px;
}
<html>
<head>
<title>Single Demo</title>
<script src="//cdn.bootcss.com/jquery/2.2.1/jquery.js"></script>
<script src="//cdn.bootcss.com/angular.js/1.4.7/angular.js"></script>
</head>
<body ng-app="app" ng-controller="homeCtrl">
<div class="container">
<table class="table table-striped">
<tr>
<th></th>
<th ng-repeat="department in departments" style="vertical-align:top" colspan="2">{{department}}</th>
</tr>
<tr ng-repeat="time in times">
<td>{{weekdays[$index]}}</td>
<td ng-repeat-start="(key,dept) in time">{{times[$index][key].start}}</td>
<td ng-repeat-end>{{times[$index][key].end}}</td>
</tr>
</table>
</div>
</body>
</html>

angular angular-table dynamic header name

I use angular and angular-table to display multiple tables on the same page.
I need to create dynamic table with dynamic header and dynamic content.
Plunkr her
This is a working example with non dynamic header but I don't find how to make dynamic
The controller :
angular.module('plunker', ['ui.bootstrap',"angular-table","angular-tabs"]);
function ListCtrl($scope, $dialog) {
$scope.cols= ['index','name','email'];
$scope.list = [
{ index: 1, name: "Kristin Hill", email: "kristin#hill.com" },
{ index: 2, name: "Valerie Francis", email: "valerie#francis.com" },
...
];
$scope.config = {
itemsPerPage: 5,
fillLastPage: true
};
}
HTML
<!-- this work -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="email"></td>
</tr>
</tbody>
</table>
<!-- this fail ... -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td ng-repeat='col in cols' at-implicit at-sortable at-attribute="{{col}}"></td>
</tr>
</tbody>
</table>
I am missing some think or it is not possible with this module ?
Did you know another module where you can have dynamic header and pagination ? ( i try also ngTable but have some bug issu with data not being displayed )
Through the below code, you can generate dynamic header
<table class="table table-hover table-striped">
<tbody>
<tr class="accordion-toggle tblHeader">
<th ng-repeat="(key, val) in columns">{{key}}</th>
</tr>
<tr ng-repeat="row in rows">
<td ng-if="!$last" ng-repeat="col in key(row)" ng-init="val=row[col]">
{{val}}
</td>
</tr>
</tbody>
</table>
Angular Script
var app = angular.module('myApp', []);
app.controller('myControl', function ($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/todos').success(function (data) {
$scope.columns = data[0];
$scope.rows = data;
}).error(function (data, status) {
});
$scope.key = function (obj) {
if (!obj) return [];
return Object.keys(obj);
}
});

Sorting only certain arrays in nested ngRepeat

I currently have a nested ngRepeat, where the inner loop iterates over a collection of items from its parent. An excerpt:
<div ng-repeat="person in persons">
(Irrelevant code here.)
<table>
<tr>
<th ng-click="setItemOrder('name')">Item name</th>
<th ng-click="setItemOrder('number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
By clicking the table headers, I set the itemOrder-property in my controller to the name of the property I want orderBy to use:
$scope.setItemOrder = function(order){
$scope.itemOrder = order;
}
This all works fine, except that if I click the headers in one person-div, the item-tables in all person-divs get sorted on that property.
Is there a way to make ngRepeat only apply orderBy to entries that match a certain criteria - for instance a certain index? Or should I use a different approach?
Try setting the property to respective person instance as follows:
angular.module('test', []).controller('testController', function($scope) {
$scope.persons = [{
items: [{
name: 'test',
number: 2
}, {
name: 'test1',
number: 1
}]
}, {
items: [{
name: 'test3',
number: 5
}, {
name: 'test4',
number: 4
}]
}];
$scope.setItemOrder = function(person, order) {
person.itemOrder = order;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:person.itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
You could add a ordering variable for each person and extend setItemOrder with the person object. Then you can call:
setItemOrder(person, 'name');
and then use it in the ngRepeat:
orderBy:person.itemOrder
angular.module('test', []).controller('testController', function($scope) {
$scope.ordersort=true;
$scope.orderfield='number';
$scope.persons = {
"items": [{
"name": 'test',
"number": 2
}, {
"name": 'test1',
"number": 1
}],
"item1": [{
"name": 'test3',
"number": 5
}, {
"name": 'test4',
"number": 4
}]
};
$scope.setItemOrder = function(person, order) {
$scope.orderfield=order;
person.itemOrder = order;
$scope.ordersort= !$scope.ordersort;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person | orderBy:orderfield:ordersort">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>
I have modified your example. In this example table sorting is working perfectly. But It is not sorted the particular table when I click on that table header. Anyway to sort columns by specific table?
angular.module('test', []).controller('testController', function($scope) {
$scope.persons = [{
items: [{
name: 'test',
number: 2
}, {
name: 'test1',
number: 1
}]
}, {
items: [{
name: 'test3',
number: 5
}, {
name: 'test4',
number: 4
}]
}];
$scope.setItemOrder = function(person, order) {
person.itemOrder = order;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="test" ng-controller="testController">
<div ng-repeat="person in persons">
<table>
<tr>
<th ng-click="setItemOrder(person,'name')">Item name</th>
<th ng-click="setItemOrder(person,'number')">Item number</th>
</tr>
<tr ng-repeat="item in person.items | orderBy:person.itemOrder">
<td>{{item.name}}
<td>{{item.number}}
</tr>
</table>
</div>

Can't generate <td> structure with recursive ng-repeat

I'm having some difficulties generating the desired table structure with a nest ng-repeat. I have a table header for each day of the week and I want to display three shifts in the <td> beneath that. Currently I solve this with three <span>'s in one <td>, but I would like to generate three <td>'s for each shift in on day. My html code with the repeats is:
<div>
<table>
<caption>Week: {{ week }}</caption>
<thead>
<tr>
<th ng-repeat="day in days">
<span>{{day.Date}}/{{ month }}/{{ year }}</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="day in days">
<span ng-repeat="shift in shifts">{{shift.Name}}</span>
</td>
</tr>
</tbody>
</table>
</div>
I have tried <th colspan="3"> with different placement of "day in days" repeats, but I can't seem to get the wanted structure for the table body:
<tr>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
</tr>
My question is: how can I rewrite my current code with the <span>'s so that it generates the wanted structure above.
If I understood your problem correctly then I think you are looking for ng-repeat-start & ng-repeat-stop.
HTML:
<div ng-app>
<div ng-controller="ExampleCtrl">
<table border="1">
<tr>
<td ng-repeat-start="day in days" ng-show="false"></td>
<td ng-repeat="shift in day.shifts" ng-repeat-end>shift{{shift}}</td>
</tr>
</table>
</div>
</div>
JS Controller:
function ExampleCtrl($scope) {
$scope.days = [
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
}
];
}
and the Fiddle
shifts outside days object: Fiddle update
You can create new plain list in your model to iterate over and use it instead of using nested loops. If data is to be changed then you can watch changes of dependent properties and reassemble plain list for each change. Something like this:
JavaScript
angular.module('app',[]).
controller('appController', function($scope) {
var i, j;
$scope.week = 1;
$scope.days = [{
day: 1,
month: 2,
year: 2014
}, {
day: 2,
month: 2,
year: 2014
}, {
day: 3,
month: 2,
year: 2014
}];
$scope.shifts = ['Shift1', 'Shift2', 'Shift3'];
// Create new plain list each time shifts is changed
$scope.$watchCollection('shifts', function() {
$scope.daysShifts = [];
for(i=0; i<$scope.days.length; i++) {
for(j=0; j<$scope.shifts.length; j++) {
$scope.daysShifts.push({
name: $scope.shifts[j]
});
}
}
});
$scope.addShift = function() {
$scope.shifts.push('Shift'+($scope.shifts.length+1));
}
});
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#*" data-semver="1.2.11" src="http://code.angularjs.org/1.2.11/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="appController">
<div>
<table>
<caption>Week: {{week}}</caption>
<thead>
<tr>
<th ng-repeat="day in days" colspan="{{shifts.length}}">
<span>{{day.day}}/{{day.month}}/{{day.year}}</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="dayShift in daysShifts">
<span>{{dayShift.name}}</span>
</td>
</tr>
</tbody>
</table>
</div>
<button ng-click="addShift()">Add Shift</button>
</body>
</html>
Plunker: http://plnkr.co/edit/zZYrurhp3HQA9Jp9QHDo?p=preview

ng-repeat does not work with the list defined in a service

I am new to angular and I am trying to learn, I have a table which I try to fill it with an array that I have:
<table ng-controller="repeatTest">
<tr>
<td>name</td>
<td>family name</td>
<td>score</td>
</tr>
<tr ng-repeat="item in list">
<td>{{ item.name }}</td>
<td>{{ item.familyName }}</td>
<td>{{ item.score }}</td>
</tr>
</table>
and my javascript code is as follow:
app.controller('repeatTest', function($scope, sharedService) {
$scope.list = [ {
name : 'hamed',
familyName : 'Minaee',
score : '100'
}, {
name : 'hamed',
familyName : 'Minaee',
score : '100'
} ];
});
which works perfectly fine but when I use service to hold he array that I have the table does not render, here is the javascript that I use which does not work:
app.service('sharedService', function() {
this.list = [ ];
});
app.controller('repeatTest', function($scope, sharedService) {
sharedService.list = [ {
name : 'ddd',
familyName : 'sss',
score : '100'
}, {
name : 'www',
familyName : 'aaa',
score : '100'
} ];
});
Can anyone help me? How can I make my code work with the second approach?
In angular, any values you wish to access in the view layer need to be attached to either the controller as "this" or to "$scope".
You set "sharedService.list" equal to a value, but that's not available to the view, so "list" will be undefined in your ng-repeat.
What you'd want to do in your controller is:
$scope.list = sharedService.list
and then define your list as:
this.list = [...some list here...]; in your service.
You have to add it to $scope. Often times the service is doing an AJAX call. See this Plunker for a working example: http://plnkr.co/edit/Yx6GYqnSLTzGD2TfB2p8?p=info
var app = angular.module("app", []);
app.service('sharedService', function() {
this.list = [{
name: 'ddd',
familyName: 'sss',
score: '100'
}, {
name: 'www',
familyName: 'aaa',
score: '100'
}];
});
app.controller('repeatTest', function($scope, sharedService) {
$scope.list = sharedService.list ;
});
And the HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js" data-require="angular.js#1.5.0" data-semver="1.5.0"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body ng-app="app">
<table ng-controller="repeatTest">
<tr>
<td>name</td>
<td>family name</td>
<td>score</td>
</tr>
<tr ng-repeat="item in list">
<td>{{item.name}}</td>
<td>{{item.familyName}}</td>
<td>{{item.score}}</td>
</tr>
</table>
</body>
</html>
app.service('sharedService', function(){
this.list = [ {
name : 'ddd',
familyName : 'sss',
score : '100'
}, {
name : 'www',
familyName : 'aaa',
score : '100'
} ];
});
app.controller('repeatTest', function($scope, sharedService){
$scope.list = sharedService.list;
});
The simple approach is define data in service and use that service in controller and bind data using $scope.
<table ng-controller="repeatTest">
<tr>
<td>name</td>
<td>family name</td>
<td>score</td>
</tr>
<tr ng-repeat="item in list">
<td>{{ item.name }}</td>
<td>{{ item.familyName }}</td>
<td>{{ item.score }}</td>
</tr>
</table>

Resources