How to get SUM of the table field? - Angularjs & Sqlite - javascript

I'm trying to get the sum of my table row (amount) with Angularjs which is connected to my sqlite database
I have managed to build CRUD operations perfectly but now I'm stuck on getting the sum of my amount field
Here's part of my html code:
<table id="tableSales" ng-init="listSales()">
<thead class="bz-tablecell">
<tr>
<th id="table-checkbox"><input type="checkbox" onclick="toggle(this);" id="chk-all"></th>
<th><b>Name</b></th>
<th><b>Amount</b></th>
<th><b>Quantity</b></th>
<th><b>Customer</b></th>
<th><b>Date</b></th>
<th class="export-ignore"><b>Status</b></th>
<th class="export-ignore"><b>Actions</b></th>
</tr>
</thead>
<tbody>
<tr class="bz-tablecell" dir-paginate="sale in sales|filter:search|itemsPerPage:20">
<td id="table-checkbox"><input type="checkbox"></td>
<td style="font-weight: 600">{{sale.name}}</td>
<td>{{sale.amount | currency: "TZS "}}</td>
<td>{{sale.quantity}}</td>
<td>{{sale.customer}}</td>
<td>{{sale.date}}</td>
<td class="export-ignore"><span class="approved" style="border-radius: 0 !important;">{{sale.status}}</span></td>
<td class="export-ignore"><a ng-click="delete(sale)">Manage</a></td>
</tr>
<tr ng-if="sales.length <= 0">
<td colspan="8" rowspan="4" class="center empty-state">
<b class="top">There are no sales yet!</b>
<br>Start by adding a new one.
</td>
</tr>
</tbody>
</table>
And here's is my angularjs code which do CRUD operations:
"USE STRICT";
app.controller("salesController", function ($scope, $location, dbService) {
$scope.sub = {
'title': 'Sales Orders'
}
$scope.listSales = function () {
//FETCH
dbService.runAsync("SELECT * FROM sales WHERE active = 1", function (data) {
$scope.sales = data;
});
}
$scope.save = function () {
if ($scope.sale.id) {
//EDIT
var id = $scope.sale.id;
delete $scope.sale.id;
delete $scope.sale.$$hashKey;
dbService.update('sales', $scope.sale, {
id: id
});
} else {
//SAVE
dbService.insert('sales', $scope.sale);
}
$scope.sale = {};
$scope.listSales();
}
$scope.delete = function (data) {
//DELETE
if (confirm("Are you sure you want to delete this sale?")) {
dbService.update('sales', {
active: 0
}, {
id: data.id
});
$scope.listSales();
}
}
});
What I need to do is get all sum of amount field, please help. Thank you

To compute a sum:
$scope.listSales = function () {
//FETCH
dbService.runAsync("SELECT * FROM sales WHERE active = 1", function (data) {
$scope.sales = data;
//COMPUTE Sum
$scope.sum = data.reduce( ( (_,sum) => sum + _.amount) , 0);
});
}
For more information, see
MDN JavaScript Reference - array.reduce

Related

Pagination in AngularJS / JavaScript from Nodejs application

I am trying to implement the simplest pagination in my website. I do not know where to start. I am a beginner at Web Development.
Here is my code for my index.html:
<div ng-controller="searchCtrl">
<h2 id="zoekTable">Zoeken</h2>
<form>
<table class="table">
<tr>
<td> </td>
<td><button type="submit" class="btn btn-edit" ng-click="searchSystem()">Zoek</button> <button type="button" class="btn" ng-click="displayAllUsers()">Toon alle gebruikers</button></td>
</tr>
</table>
</form>
<h2>Gebruikers</h2>
<table class="table" id="tableResults">
<thead>
<tr>
<td>Gebruikersnaam</td>
<td>Volledige naam</td>
<td>Woonplaats</td>
<td>Bezit rijbewijs</td>
<td>Bekijk CV</td>
</tr>
</thead>
<tr ng-if="results.length === 0">
<td>Geen.</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr ng-if="results.length !== 0" ng-repeat="result in results">
<td>{{result.gebruikersnaam}}</td>
<td>{{result.naam}}</td>
<td>{{result.woonplaats}}</td>
<td>{{result.rijbewijs==1?"Ja":"Nee"}}</td>
<td><button ng-click="viewCV(result.gebruikersnaam)">Bekijk CV</button></td>
</tr>
</table>
</div>
Here is my code for my AngularJS side:
app.controller('searchCtrl', function ($scope, $http, $location) {
$scope.displayAllUsers = function () {
$http.get("/gebruikers")
.success(function (users) {
success2("Gebruikers gevonden!", "zoekTable");
$scope.results = users;
})
.error(function (err) {
alert(err);
clearResults();
});
};
function clearResults() {
$scope.results = "";
$scope.results.length = 0;
}
});
And finally my Node.Js code:
app.get("/gebruikers", function (req, res) {
var rijen;
l("Bezig met ophalen van gebruikers...");
connection.query("SELECT * FROM gebruikers INNER JOIN personalia ON gebruikers.gebruikersnaam = personalia.gebruikersnaam WHERE done='1';", function (err, rows) {
if (err) {
l("ERROR: " + err);
res.sendStatus(500);
} else {
if (rows.length >= 1) {
rijen = rows;
l("Gebruikers gevonden!");
res.status(200).send(rows);
} else {
l("Geen gebruikers gevonden!");
res.status(404).send("!Geen gebruikers gevonden!");
}
}
});
});
I maybe getting 1000 users from my database and I would like to add pagination as simple as possible. Hoe can I do that?
Your backend needs to be able to handle two params. Limit and Skip. Limit is the number of records you will be fetching, skip is the number of records you will omit.
So you need something like this:
$scope.page = function(_page) {
var query = {
skip: 50 * (_page - 1),
limit: 50
};
}
If page is 1 you will omit 0 records. If page is 2, you will omit 50...and so on.
You will need to combine this with the proper query in the backend plus as #GillesC mentioned, check out that pagination directive for Angular. http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs

Angular - link two API sources in table based on ID FK

I'm really new to Angular and i'm trying to create a list of user transactions that presents the time of the action and the user's name. In my audit API I have an action ID and the User FK which associates with my User API and i'm displaying it as follows:
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>**{{audit.audit_user_fk}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
My Apis are as follows:
AUDIT
[
{
"audit_id": "1",
"audit_date_time": "2016-01-28 12:46:20",
"audit_user_fk": "97"
}
]
USER
[
{
"user_id": "97",
"user_full_name": "Mr.User",
}
]
Controller, which is working fine GETting the data from each API:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
}]);
So my main issue i'm having is getting the user name in the table instead of the foreign key value. I've stripped out a lot of this just so we can focus on the main problem. Getting the user name from the user API, based on the FK in the Audit API and repeated based on the items in the Audit API.
Any help greatly appreciated and apologies for the noob question!
Create a custom filter.
app.filter("lookupUser", function() {
function lookup (idNum, userList) {
var userName = "UNKNOWN";
angular.forEach(userList, function(user) {
if ( user.user_id == idNum ) {
userName = user.user_full_name;
};
});
return userName;
};
return lookup;
});
Then in your template:
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>{{audit.audit_user_fk | lookupUser : auditUser }}</td>
</tr>
You could do something like this:
Controller:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
$scope.getUserName = function (id) {
var result = $scope.users.filter(function( user ) {
return user.user_id == id;
});
if (angular.isDefined(result) && result.length > 0) {
return result[0].user_full_name;
} else {
return "--";
}
}
}]);
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data">
<td>{{audit.audit_date_time}}</td>
<td>**{{getUserName(audit.audit_user_fk)}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
I don't know where the users array are, so I called $scope.users.

Enable JQuery Sortable on dropdown select

I am currently using jQuery sortable to rearrange table rows in my application. I have this all working fine except I need to introduce functionality where dragging is only enabled when the user selects a team from a drop-down box on the page. The idea is that when the user first arrives onto the view, a list of team rows will be displayed. They user can select a unique team from the dropdown and filter all the rows associated with that particular team. This is when I want to be able to enable the sortable functionality. I am using the sortable library in an Angular directive, and I am filtering all table rows in the Angular controller. If someone could please point me in the right direction I would be extremely grateful. Here is my code:
myTeam.html
<div class="row">
<!-- Header Start -->
<banner-directive banner-title="Favorite Teams">
</banner-directive>
<!-- Header End -->
<div id="wrap">
<div class="container">
<div class="row">
<div class="team-order">
<div class="team-select-wrapper" style="display: inline-block">
<h2>Select team</h2>
<select class="form-control" name="teamList" ng-model="selectedteam" ng-options="team as team.name for team in teams" ng-change="onTeamSelected()">
<option value="" disabled selected>Select a Team</option>
</select>
</div>
<strong>{{teammatches.length}}</strong>Teams:
</div>
<team-order-matches matches="teammatches" teamorder="teamorder"></team-order-matches>
</div>
</div>
</div>
</div>
<div class="team-order-matches">
<div class="content">
<table class="table" id="draggable_rows">
<thead style="position: fixed; top:182px;">
<tr>
<th class="table-col-medium">
Name
</th>
<th class="table-col-medium">
Team
</th>
<th class="table-col-medium">
Amount
</th>
<th class="table-col-large">
Win
</th>
<th class="table-col-medium">
Loss
</th>
<th class="table-col-medium">
Draw
</th>
<th class="table-col-medium">
Manager
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="team in teams" class="team-order-row" id="{{team._id}}">
<td class="table-col-medium" style="position: relative;">
Name
</td>
<td class="table-col-medium">
Example
</td>
<td class="table-col-medium">
Example
</td>
<td class="table-col-large">
Example
</td>
<td class="table-col-medium">
Example
</td>
<td class="table-col-medium">
Example
</td>
<td class="table-col-medium">
Example
</td>
</tr>
</tbody>
</table>
</div>
</div>
This is my controller
function TeamOrderMatchesController($scope,$location, $filter, $window, LocaleService) {
$scope.teammatches = [];
$scope.sortColumn = sortColumn;
$scope.onTeamSelected = onTeamSelected;
//filters the list to team that is selected
function onTeamSelected(){
TeamService.getMatchEvalOrder($scope.selectedteam._id).then(function(result){
$scope.runorder = result.result;
$scope.teammatches = orderByEvalOrder($scope.runorder, filterMatchesByTeam())
});
}
//Gets the unique team list for the dropdown menu
function getTeamList(){
var teams = _.map($scope.matches, function(match){
var liveVersion = _.find(match.versions, function(version){
return match.liveVersion === version.version;
});
return liveVersion.team;
});
var uniqueTeams = _.uniq(teams, function(team){
return team._id;
});
return uniqueTeams;
}
//Captures the evaluation order of the rows dragged and dropped
function orderByEvalOrder(orderedMatchIds, matches) {
var orderedMatches = [];
if(orderedMatchIds && orderedMatchIds.length > 0){
_.each(orderedMatchIds, function(orderedmatch){
var foundMatch = _.find(matches, function(m) {
return m._id == orderedmatch;
});
if(foundMatch) {
orderedMatches.push(foundMatch);
}
});
_.each(matches, function(match){
if (orderedMatchIds.indexOf(match._id) < 0) {
orderedMatches.push(match);
}
});
}
else{
orderedMatches = matches;
}
return orderedMatches;
}
//Filters the matches on the team selected
function filterMatchesByTeam() {
return _.filter($scope.matches, function(match){
var liveVersion = _.find(match.versions, function (version) {
return match.liveVersion === version.version;
});
return liveVersion.team._id === $scope.selectedteam._id;
});
}
function sortColumn(predicate, reverse) {
$scope.sortedColumn = predicate;
$scope.matches = $filter('orderBy')($scope.matches, matchPredicate, reverse);
function matchPredicate(match) {
var column;
if (shouldSortOnRoot()) {
column = match[predicate];
} else {
setVersionColumn();
}
return column;
function shouldSortOnRoot() {
return match.hasOwnProperty(predicate);
}
function setVersionColumn() {
var tempColumn = getLiveVersion(match)[predicate];
if (tempColumn.name) {
column = tempColumn.name;
} else {
column = tempColumn;
}
}
}
}
}
enter code here
exampleApp.directive('teamOrderMatches',[ '_',teamOrderMatches]);
function teamOrderMatches(_) {
return {
restrict: 'E',
scope: {
onsave: '&',
oncancel: '&',
matches: '=',
isDraggable: '&',
runorder: '='
},
link: function(scope, elem){
var table = elem.find("#draggable_rows tbody");
function updateScope() {
var ids = _.map(table.children(), function(child){
return child.id;
});
var idsWithoutEmpty = _.filter(ids, function(id) {
return id && id !== "";
});
scope.runorder = idsWithoutEmpty;
console.log(scope.teamorder);
scope.$apply();
}
table.sortable({
axis: 'y',
items: 'tr',
connectWith: 'table',
placeholder: "highlight",
tolerance: 'pointer',
scroll: true,
sort: function(event, ui) {
var currentScrollTop = $(window).scrollTop(),
topHelper = ui.position.top,
delta = topHelper - currentScrollTop;
setTimeout(function() {
$(window).scrollTop(currentScrollTop + delta);
}, 5);
},
//Helper function to keep table from collapsing when being sorted
helper: function(e, tr){
var $originals = tr.children();
var $helper = tr.clone().addClass('clone');
$helper.children().each(function(index)
{
$(this).width($originals.eq(index).width());
});
return $helper;
},
//The update function will update the table rows scope after they have been dragged to a new position
update: function(){
updateScope();
}
}).disableSelection();
},
controller: 'TeamOrderMatchesController'
};
}

Remove specific element from array in Knockout.JS

I am creating a multiplayer game over network so I have to react on network events.
I have this simple code, but the removePlayer method doesnt work. The addPlayer() works fine.
<table id="userlist2" class="tablesorter" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Queue</th>
<th>Points</th>
</tr>
</thead>
<tbody data-bind="foreach: players">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: queue"></td>
<td data-bind="text: score"></td>
</tr>
</tbody>
</table>
function PlayerViewModel() {
var self = this;
self.players = ko.observableArray();
self.addPlayer = function (Name, QueuePos, Score) {
self.players.push({
name: Name,
queue: QueuePos,
score: Score
});
}
self.removePlayer = function (Name) {
for (var i = 0; i < self.players().length; i++) {
if (self.players()[i].name == Name) console.log(i);
self.players().splice(i, 1);
}
}
}
players = new PlayerViewModel();
ko.applyBindings(players);
players.addPlayer('Player1', '0', '0');
players.addPlayer('Player2', '0', '0');
players.removePlayer('Player2');
Heres the http://jsfiddle.net/xseTc/
You have to use the remove function :
self.removePlayer = function (Name) {
self.players.remove(function(player) {
return player.name == Name;
});
}
See fiddle
html
<table id="userlist2" class="tablesorter" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Queue</th>
<th>Points</th>
</tr>
</thead>
<tbody data-bind="foreach: players">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: queue"></td>
<td data-bind="text: score"></td>
</tr>
</tbody>
</table>
javascript
function PlayerViewModel() {
var self = this;
self.players = ko.observableArray();
self.addPlayer = function (Name, QueuePos, Score) {
self.players.push({
name: Name,
queue: QueuePos,
score: Score
});
}
self.removePlayer = function (Name) {
self.players.remove(function(player) {
return player.name == Name;
});
}
}
players = new PlayerViewModel();
ko.applyBindings(players);
players.addPlayer('Player1', '0', '0');
players.addPlayer('Player2', '0', '0');
players.removePlayer('Player2');
Working remove function:
self.removePlayer = function (name) {
self.players.remove(function(player) {
return player.name == name
});
}
your code is fine except 2 error you have:
if (self.players()[i].name == Name) console.log(i);
self.players().splice(i, 1);
first here you are executing 2 lines so to execute them both you need to use {} so replace it with:
if (self.players()[i].name == Name) {
console.log(i);
self.players.splice(i, 1);
}
second to use splice you done need to call your observable array with () so you to use it as following :
self.players.splice(i, 1);
Working Demo
If you add view models to the array of players like this:
self.addPlayer = function (Name, QueuePos, Score) {
self.players.push(new PlayerVM(Name, QueuePos, Score)));
}
Then you can remove the player object like this:
self.removePlayer = function (player) {
self.players.remove(player);
}
Or from within the player vm:
parentVM.players.remove(self);
As per the best source from knockout site : https://knockoutjs.com/documentation/observableArrays.html
You can use remove method direct --
self.players.remove(self.players()[i]);

KnockoutJS - extending the shopping cart example

I'm currently trying to extend the KnockoutJS shopping cart example to preload existing rows from a JSON collection.
Say, I have an object like this:
var existingRows = [{
"Category":Classic Cars,
"Product":2002 Chevy Corvette,
"Quantity":1,
}, {
"Category":Ships,
"Product":Pont Yacht,
"Quantity":2,
}];
I am trying to modify the example so that on load it populates the grid with two rows, with the comboboxes pre-set to the items in the JSON object.
I can't seem to get this object playing nicely with JSFiddle, but I've got as far as modifying the Cart and CartLine functions, and ApplyBindings call as follows:
var CartLine = function(category, product) {
var self = this;
self.category = ko.observable(category);
self.product = ko.observable(product);
// other code
}
var Cart = function(data) {
var self = this;
self.lines = ko.observableArray(ko.utils.arrayMap(data, function(row) { return new CartLine(row.Category, row.Product);}))
// other code
}
ko.applyBindings(new Cart(existingRows));
This correctly inserts two rows on load, but does not set the drop down lists. Any help would be much appreciated :)
The problem is that the values of the category and product observables in the CartLine object are not simple strings. They are actual objects, e.g. category refers to a specific category from the sample data that's provided in that example, same with product.
But you're just setting them to strings.
(Another problem is that your JS object existingRows is not valid javascript because of quotes missing around the string)
To get that example working with your existingRows object you could extract the relevant category and product from the sample data:
var Cart = function(data) {
// Stores an array of lines, and from these, can work out the grandTotal
var self = this;
self.lines = ko.observableArray(ko.utils.arrayMap(data, function(row) {
var rowCategory = ko.utils.arrayFirst(sampleProductCategories, function(category) {
return category.name == row.Category;
});
var rowProduct = ko.utils.arrayFirst(rowCategory.products, function(product) {
return product.name == row.Product;
});
return new CartLine(rowCategory, rowProduct, row.Quantity);
}));
// other code
}
Updated fiddle: http://jsfiddle.net/antishok/adNuR/664/
<h1> Online shopping</h1>
<button id="btnAdd" data-bind='click: addLine'>Add product</button><br /><br />
<table width='100%'>
<thead>
<tr>
<th width='25%'>Product</th>
<th class='price' width='15%'>Price</th>
<th class='quantity' width='10%'>Quantity</th>
<th class='price' width='15%'>Subtotal (in rupees)</th>
<th width='10%'> </th>
</tr>
</thead>
<tbody data-bind='foreach: items'>
<tr>
<td>
<select data-bind='options: products, optionsText: "name", optionsCaption: "Select...", value: product'> </select>
</td>
<td class='price' data-bind='with: product'>
<span data-bind='text: (price)'> </span>
</td>
<td class='quantity'>
<input data-bind='visible:product, value: quantity, valueUpdate: "afterkeydown"' />
</td>
<td class='price'>
<span data-bind='visible: product, text: subtotal()' > </span>
</td>
<td>
<a href='#' data-bind='click: $parent.removeLine'>Remove</a>
</td>
</tr>
</tbody>
</table>
<h2>
Total value: <span data-bind='text: grandTotal()'></span> rupees
</h2>
$(document).ready(function () {
$("#btnAdd").button();
ko.applyBindings(new OnlineShopping());
});
function formatCurrency(value) {
return "$" + value.toFixed(2);
}
var Item = function () {
var self = this;
self.product = ko.observable();
self.quantity = ko.observable(1);
self.subtotal = ko.computed(function () {
var result = self.product() ? self.product().price * parseInt("0"+self.quantity(), 10) : 0;
return result;
});
};
var OnlineShopping = function () {
var self = this;
// List of items
self.items = ko.observableArray([new Item()]);
// Compute total prize.
self.grandTotal = ko.computed(function () {
var total = 0;
$.each(self.items(), function () { total += this.subtotal() })
return total;
});
// Add item
self.addLine = function () {
self.items.push(new Item())
};
// Remove item
self.removeLine = function () {
self.items.remove(this)
};
};
// Item collection
var products = [{ name: "IPhone", price: "45000" }, { name: "Galaxy Y", price: "7448" }, { name: "IPad", price: "25000" }, { name: "Laptop", price: "35000" }, { name: "Calci", price: "750"}];

Categories