I need helping with calculating the total amount of tickets.number in this ng-repeat
HTML
<tr ng-repeat="tickets in listTickets | filter: searchText | orderBy: sortorder:reverse">
<td>{{ tickets.match }}</td>
<td>{{ tickets.number }}</td>
<td>{{ tickets.company }}</td>
<td>{{ tickets.contact }}</td>
<td>{{ tickets.mail }}</td>
<td>{{ tickets.phone }}</td>
<td><button class="btn btn-info" ng-click="edit(tickets._id)">Edit</button> </td>
<td><button class="btn btn-danger" ng-click="delete(tickets._id)">Radera</button></td>
</tr>
<tr>
<td colspan="8"> Total of: {{ totalTickets() }} tickets</td>
</tr>
My controller.js
$scope.totalTickets = function(){
}
You can use ECMAScript 5 Array.prototype.map() and Array.prototype.reduce() to get the total sum.
AngularJS method totalTickets passing the filteredArr array parameter as you are filtering in the view ng-repeat:
$scope.totalTickets = function (filteredArr) {
return filteredArr
.map(function (o) {
return o.number;
})
.reduce(function (a, b) {
return a + b;
}, 0);
};
AngularJS view:
<tr ng-repeat="tickets in listTickets | filter: searchText as filteredArr | orderBy: sortorder:reverse">
<td>{{ tickets.match }}</td>
<td>{{ tickets.number }}</td>
<td>{{ tickets.company }}</td>
<td>{{ tickets.contact }}</td>
<td>{{ tickets.mail }}</td>
<td>{{ tickets.phone }}</td>
<td><button class="btn btn-info" ng-click="edit(tickets._id)">Edit</button></td>
<td><button class="btn btn-danger" ng-click="delete(tickets._id)">Radera</button></td>
</tr>
<tr>
<td colspan="8"> Total of: {{ totalTickets(filteredArr) }} tickets</td>
</tr>
Code example:
var listTickets = [{number: 1},{number: 2},{number: 3},{number: 4}],
total = listTickets.map(o => o.number).reduce((a, b) => a + b, 0);
console.log(total);
You can also use filter to calculate a total.
Html
<tr ng-repeat="tickets in listTickets | filter: searchText | orderBy: sortorder:reverse">
<td>{{ tickets.match }}</td>
<td>{{ tickets.number }}</td>
<td>{{ tickets.company }}</td>
<td>{{ tickets.contact }}</td>
<td>{{ tickets.mail }}</td>
<td>{{ tickets.phone }}</td>
<td><button class="btn btn-info" ng-click="edit(tickets._id)">Edit</button> </td>
<td><button class="btn btn-danger" ng-click="delete(tickets._id)">Radera</button></td>
</tr>
<tr>
<td colspan="8"> Total of: <span data-ng-bind="tickets.total=(listTickets | total:'number')"></span> tickets</td>
</tr>
Controller.js
app.filter('total', function(){
return function(input, property) {
var total = 0;
angular.forEach(input, function(value, key) { total += parseFloat(value[property]) });
return total;
}
})
The cleanest solution involves the ngRepeat as keyword (https://docs.angularjs.org/api/ng/directive/ngRepeat) and a custom total filter as posted by #aravinthan-k.
as keyword has to be last in the filter stack in the ng-repeat. Whatever you do in between with different filters, the as alias will have the final result.
total filter is easily reusable all over your code.
Fiddle: http://jsfiddle.net/25g9hzzd/2/
Example HTML:
<div ng-app="myapp">
<div ng-controller="Ctrl">
<h1>List</h1>
<input type="text" ng-model="form.searchText"/>
<ul>
<li ng-repeat="item in list | filter: form.searchText as result">
{{item.title}}
</li>
<li>TOTAL: {{result | total:'number'}}</li>
</ul>
</div>
</div>
Example filter (by #aravinthan-k) and the controller:
var app = angular.module('myapp', []);
app.filter('total', function(){
return function(input, property) {
var total = 0;
angular.forEach(input, function(value, key) { total += parseFloat(value[property]) });
return total;
}
});
app.controller('Ctrl', function($scope){
$scope.form = {
searchText: ''
};
$scope.list = [
{
title: 'A',
number: 1
},
{
title: 'AB',
number: 2
},
{
title: 'ABC',
number: 3
},
{
title: 'ABCD',
number: 4
},
];
});
Because you've filtered the list and need to count only the filtered elements, you'll need to pre filter the list in the controller. You can use the search filter in your controller to pre filter the list.
// Inject $filter so that it can be used in the controller
function MyController($filter) {
$scope.filteredTickets = [];
// filter the tickets and count how many there are in the filtered list
function updateTickets(searchTerm) {
$scope.filteredTickets = $filter('search')($scope.listTickets, $scope.searchText);
// Use Array.reduce to add up the number of tickets
$scope.ticketCount = $scope.filteredTickets.reduce(function(count, ticket) {
return count + ticket.number;
}, 0);
}
// update the ticket count on initialisation
updateTickets($scope.searchText);
// update ticket count when search text changes
$scope.$watch('searchText', function(newValue, oldValue) {
if (newValue !== oldValue) {
updateTickets(newValue);
}
});
}
Then in your HTML you can ng-repeat through the pre filtered tickets, and use the pre calculated total.
<tr ng-repeat="tickets in filteredTickets | orderBy: sortorder:reverse">
...
</tr>
<tr>
<td>Total of {{ ticketCount }} tickets</td>
</tr>
Related
I am able to show all data from my products record in Firebase DB, what i want now is to delete a certain record that i select.
I got a bit of the documentation of Firebase but i'm not so good with VueJs, although i think this is more of a JavaScript problem.
What i get on my console when i click the delete link is:
Error: Firebase.child failed: First argument was an invalid path:
"undefined". Paths must be non-empty strings and can't contain ".",
"#", "$", "[", or "]"
Here is my code:
<template>
<tbody v-for="(key, value, index) in products">
<tr v-for="k, val in key">
<td>{{ k.name }}</td>
<td>{{ k.description }}</td>
<td>{{ k.oldPrice }}</td>
<td>{{ k.price }}</td>
<td>{{ k.prodId }}</td>
<td>{{ k.sellerName }}</td>
<td><span class="glyphicon glyphicon-trash btn-delete-style" v-on:click="removeProduct(k)" title="Delete Product"></span></td>
</tr>
</tbody>
</template>
<script>
removeProduct: function (product) {
console.log("Product:" + product);
productsRef.child(product['.key']).remove();
toastr.success("Product deleted successfully");
}
</script>
Below you can see my DB:
Any help is appreciated, Thank you.
You need to reference first to that record and then call the remove function, here is an example:
<template>
<tbody v-for="(key, value, index) in products">
<tr v-for="k, val in key">
<td>{{ k.name }}</td>
<td>{{ k.description }}</td>
<td>{{ k.oldPrice }}</td>
<td>{{ k.price }}</td>
<td>{{ k.prodId }}</td>
<td>{{ k.sellerName }}</td>
<td><span class="glyphicon glyphicon-trash btn-delete-style" v-on:click="removeProduct(k, k.sellerId, k.prodId)" title="Delete Product"></span></td>
</tr>
</tbody>
</template>
<script>
removeProduct: function (product, sellerID, prodId) {
var currentRef = db.ref('products/' + sellerID + '/' + prodId);
currentRef.remove();
toastr.success("Product deleted successfully");
}
</script>
I think you should take product id from prodid
productsRef.child(product['prodid']).remove()
I have a table like this that displays data including several navigation properties :
<table class="table afcstandings">
<thead>
<tr>
<th>team</th>
<th>coach</th>
<th>w</th>
<th>l</th>
<th>t</th>
<th>fa</th>
<th>agst</th>
<th>diff</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let standing of standingsAFCEast">
<!-- property binding rather than interpolation-->
<td>{{ standing.team.teamName }}</td>
<td>{{ standing.team.coach.coachName }}</td>
<td>{{ standing.won }}</td>
<td>{{ standing.lost }}</td>
<td>{{ standing.tied }}</td>
<td>{{ standing.pointsFor }}</td>
<td>{{ standing.pointsAgainst }}</td>
<td>{{ standing.pointsDifference }}</td>
</tr>
</tbody>
</table>
Here is the data structure that is being read :
[{"team":{"teamId":22,"teamName":"Carolina Panthers","coach":{"coachId":61,"coachName":"J Smith"},"division":{"divisionId":2,"divisionName":"NFC West"},"headerImage":"","logoImage":"","hex":"","r":null,"g":null,"b":null},"won":2,"lost":1,"tied":0,"pointsFor":82,"pointsAgainst":62,"pointsDifference":20}]
My question is, how do I display this data using ngx-datatable? I have tested with 3 fields, teamName, coachName and won, and am able to display the won field, but not the others, as I am not sure how to drill down into the team object or the coach object.
<ngx-datatable class="ngx-datatable" [rows]="standingsAFCEast">
<ngx-datatable-column name="team.teamName" [width]="300"></ngx-datatable-column>
<ngx-datatable-column name="team.coach.coachName"></ngx-datatable-column>
<ngx-datatable-column name="won"></ngx-datatable-column>
</ngx-datatable>
Any advice would be really appreciated!
After looking at the basic examples, I made this work (Plunker here):
#Component({
selector: 'my-app',
template: `
<div>
<ngx-datatable
[rows]="rows"
[columns]="columns"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="'auto'"
[reorderable]="reorderable">
</ngx-datatable>
</div>
`
})
export class AppComponent {
standingsAFCEast = [{
"team":{
"teamId":22,
"teamName":"Carolina Panthers",
"coach":{
"coachId":61,
"coachName":"J Smith"
},
"division":{
"divisionId":2,
"divisionName":"NFC West"
},
"headerImage":"",
"logoImage":"",
"hex":"",
"r":null,
"g":null,
"b":null
},
"won":2,
"lost":1,
"tied":0,
"pointsFor":82,
"pointsAgainst":62,
"pointsDifference":20
}]
get rows () {
return this.standingsAFCEast.map(standing => ({
team: standing.team.teamName,
coach: standing.team.coach.coachName,
w: standing.won,
l: standing.lost,
t: standing.tied,
fa: standing.pointsFor,
agst: standing.pointsAgainst,
diff: standing.pointsDifference
}))
}
// columns = [{name:'team'}, {name:'coach'}, {name:'w'}, {name:'l'}, {name:'t'}, {name:'fa'}, {name:'agst'}, {name:'diff'}]
columns = Object.keys(this.rows[0]).map(val => ({name: val}))
}
Let me know if this helps!
I want to search in column name or number only, currently i'm only searching in column name.
<input type="text" ng-model="test.name" placeholder="start typing..">
my expressions,
<tr ng-repeat="x in names | filter:test | limitTo:totalDisplayed">
<td>{{ x.name }}</td>
<td>{{ x.number}}</td>
<td>{{ x.city }}</td>
<td>{{ x.country }}</td>
</tr>
Create a custom filter to accomplish this.
html
<input type="text" ng-model="test.name" placeholder="start typing..">
<tr ng-repeat="x in names | myFilter: test">
<td>{{ x.name }}</td>
<td>{{ x.number}}</td>
<td>{{ x.city }}</td>
<td>{{ x.country }}</td>
</tr>
js filter
angular.module('myApp').filter('myFilter', function () {
return function (list, input) {
//input is test object and list is your current array you want to return a filtered array
var myArray = [];
list.forEach(function(o, i){
if(o.name.indexOf(input.name) > -1 || o.number.indexOf(input.name) > -1 )
myArray.push(o);
});
return myArray
};
});
iam trying to get the code in a Element Template:
rent.html
<td>{{ rent.id }}</td>
<td>{{ rent.auto }}</td>
<td>{{ rent.person }}</td>
<td>{{ rent.title }}</td>
<td>{{ rent.start }}</td>
<td>{{ rent.end }}</td>
<td><a ng-href="#" ng-click="acceptRent(rent.id)"><img src="bundles/chriskfzbuchung/images/accept.png" width="15" ng-hide="rent.buchungsStatus == 1"></a></td>
<td><a ng-href="#" ng-click="declineRent(rent.id)"><img src="bundles/chriskfzbuchung/images/decline.png" width="15" ng-hide="rent.buchungsStatus == 2"></a></td>
controller.js
kfzModule.directive("kfzRent", function(){
return {
restrict: 'E',
templateUrl: '/kfz-buchung/rent.html'
};
});
overview.html
<tr kfz-rent ng-repeat="rent in rents" ng-class="{'success' : rent.buchungsStatus == 1, 'danger' : rent.buchungsStatus == 2}">
</tr>
I dont know how to deal with the rest in overview.html.
I finally want just an <kfz-rent></kfz-rent>.
Thanks!
This should work:
<kfz-rent ng-repeat="rent in rents" ng-class="{'success' : rent.buchungsStatus == 1, 'danger' : rent.buchungsStatus == 2}">
<td>{{ rent.id }}</td>
<td>{{ rent.auto }}</td>
<td>{{ rent.person }}</td>
<td>{{ rent.title }}</td>
<td>{{ rent.start }}</td>
<td>{{ rent.end }}</td>
<td><a ng-href="#" ng-click="acceptRent(rent.id)"><img src="bundles/chriskfzbuchung/images/accept.png" width="15" ng-hide="rent.buchungsStatus == 1"></a></td>
<td><a ng-href="#" ng-click="declineRent(rent.id)"><img src="bundles/chriskfzbuchung/images/decline.png" width="15" ng-hide="rent.buchungsStatus == 2"></a></td>
</kfz-rent>
The code for ng-repeat seems to be fine. But you have to create the array in your controller:
$scope.rents = [];
Dont forget to make a alias for your controller
kfzModule.directive("kfzRent", function(){
return {
restrict: 'E',
templateUrl: '/kfz-buchung/rent.html'
};
},
controllerAs: 'rentController'
};
});
Cheers,
Valentin
I'm having trouble trying to get paging to function correctly while filtering.
When the filters are active the paging numbers are not correct, and it only filters the first page of results. What I want is:
all items to be considered to start with
then filter by the text and category filters
order those filtered results
limit the results to only show the current page
update the page number to correctly show the number of pages based on the filter, not all results
Here is the ng-repeat statement i'm using:
item in items |
filter: { name: filters.name, category: filters.category } |
orderBy: predicate: reverse |
startFrom: currentPage * pageSize |
limitTo: pageSize
And the html in full:
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Category</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items | filter:{name:filters.name,category:filters.category} | orderBy:predicate:reverse | startFrom:currentPage*pageSize | limitTo:pageSize">
<td>{{ item.id || 'None' }}</td>
<td>{{ item.name || 'None' }}</td>
<td>{{ item.category || 'None' }}</td>
<td>{{ item.date | None' }}</td>
</tr>
</tbody>
</table>
<pagination total-items="totalItems" ng-model="currentPage"></pagination>
And this is the custom startFrom filter i'm using to get a page of results:
.filter('startFrom', function () {
return function (input, start) {
return input.slice(start);
};
});
You can see a working version here:
http://kmturley.github.io/angular-bootstrap/app/
Please see here: http://plnkr.co/edit/yVDZR6Zwo9P8OHT0G2Hr?p=preview
I've changed few things
JS:
$scope.updatefilters = function(category)
{
$scope.filters.category = category;
$scope.totalItems = $filter('filter')($scope.items,$scope.filters).length;
}
$scope.setPage = function (num) {
$scope.totalItems = $filter('filter')($scope.items,$scope.filters).length;
$scope.currentPage = num;
$scope.pageSize = 5;
console.log($scope.currentPage, $scope.totalItems);
};
$scope.setPage(1);
})
html:
<div ui-view="sidebar">
<div class="filters">
<h1>Filters</h1>
<h3>Category</h3>
<p>All Categories</p>
<p>Music</p>
<p>Film</p>
<p>TV</p>
</div>
</div>