Pagination in AngularJS / JavaScript from Nodejs application - javascript

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

Related

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

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

Dynamic table with JSON data and sticky collapsible rows

I'm using Angular 1 with a factory that polls a REST API for JSON data. This JSON then populates a table with ng-repeat-start, and using ng-repeat-end I have a hidden table row with additional data.
Seems rather ordinary to me.
But the problem is, when I poll the API every 5 or 10 seconds, how can I keep the collapsible table row open when the next poll occurs?
In most cases the data does not change, so there's no reason to close the collapsible row, yet it closes at every poll that my factory makes.
Here's an example of one of the tables.
<table class="pure-table pure-table-horizontal alerts-table" id="alert-nagios-host-table">
<thead>
<tr>
<th>Hostname</th>
<th>Status</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr class="parent-row" ng-repeat-start="alert in alerts" ng-click="child.expanded = !child.expanded">
<td>{{alert.hostname}}</td>
<td ng-class="{3:'grayBg', 2:'redBg', 1:'yellowBg', 0:'greenBg'}[alert.state]">{{alert.status}}</td>
<td>{{alert.output}}</td>
</tr>
<tr class="child-row" ng-init="child.expanded = false" ng-show="child.expanded" ng-repeat-end>
<td colspan=4>Duration: {{alert.duration}}</td>
</tr>
</tbody>
</table>
Here is my factory that polls the data, and an example of one of the angular controllers.
mondashApp.factory('AlertsPoller', function ($http, $timeout) {
var data = {resp: {}, count: 0};
var count=0;
var poller = function (url, success) {
count++;
$http.get(url).then(function (responseData) {
data.count = count;
data.resp = responseData.data;
success(data);
$timeout(function () {poller(url, success);}, 5000);
});
};
return {
poller: poller
};
});
mondashApp.controller('nagiosHostAlertsCtrl', function nagiosHostAlertsCtrl($scope, AlertsPoller) {
AlertsPoller.poller('/alert/nagios/host', function(response) {
$scope.alerts = response.resp.alerts;
});
});

Meteor returning NaN in the browser

I'm building a simple ordering app in Meteor and have come a cropper trying to get the order total even though I can get it to log in the console as a bona fide number - it is being rendered as NaN. Any help would be greatly appreciated.
Note the totals of individual products are appearing fine.
I have the following files:
meteorder/client/templates/orders/order_build.js:
Template.order.helpers({
'orderitems': function() {
var orderCart = [];
var orderItems = OrderItems.find({});
var total = 0;
orderItems.forEach(function(orderItem) {
var item = _.extend(orderItem, {});
var product = Products.findOne({
_id: orderItem.product
});
orderItem.productname = product.description;
orderItem.price = (Number(product.price) * orderItem.qty);
total += orderItem.price;
orderCart.push(orderItem);
});
orderCart.subtotal = total;
orderCart.tax = orderCart.subtotal * .23;
orderCart.total = orderCart.subtotal + orderCart.tax;
return orderCart;
}
})
meteorder/client/templates/orders/order_build.html:
<template name="order">
<div class="page-header">
<h1>
<small>My Order</small>
</h1>
</div>
<table class="span4 table table-striped table-bordered table-hover">
<thead>
<th>Qty</th>
<th>Product</th>
<th>Price</th>
<th></th>
</thead>
<tbody>
{{#each orderitems}}
<tr>
<td>{{qty}}</td>
<td>{{productname}}</td>
<td>{{currency price}}</td>
<td><span class="label-important label removeci">X</span></td>
</tr>
{{else}}
<tr>
<td colspan="3">No Products in Order</td>
</tr>
{{/each}}
<tr>
<td class="totalcol" colspan="2">SubTotal:</td>
<td colspan="2">{{currency orderCart.subtotal}}</td>
</tr>
<tr>
<td class="totalcol" colspan="2">Tax 6%:</td>
<td colspan="2">{{currency orderCart.tax}}</td>
</tr>
<tr>
<td class="totalcol" colspan="2">Total:</td>
<td colspan="2">{{currency orderCart.total}}</td>
</tr>
</tbody>
</table>
</template>
meteorder/client/lib/main.js:
Template.registerHelper('currency', function(num){
return '€' + Number(num).toFixed(2);
});
meteorder/server/server.js:
Meteor.methods({
addToOrder:function(qty,product,session){
check(qty, Number);
check(product, String);
check(session, String);
if(qty > 0){
OrderItems.insert({qty:qty,product:product,sessid:session});
console.log('reaching this fn', typeof qty, typeof product, typeof session);
} else{
console.log('Quantity is Zero');
}
},
removeOrderItem:function(id){
check(id, String);
OrderItems.remove({_id:id});
console.log('successfully deleted');
}
});
Here is a link to the GitHub repo
And the latest version of the deployed App
Thanks in advance!
Edit:
Just adding this in for Matthias:
Template.productItem.events({
'click .addOrder':function(evt,tmpl){
var qty1 = tmpl.find('.prodqty').value;
var qty = parseInt(qty1);
var product = this._id;
var sessid = Meteor.default_connection._lastSessionId; //stops others adding to your cart etc
Meteor.call('addToOrder',qty, product, sessid);
console.log('this is the quantity:', typeof qty, product, sessid);//stops others ad
}
});
to see if it gives a better picture of why the cart is not populating. Thanks
You're trying to use orderCart as both an array of objects and an object. You push a bunch of orderItem objects on to the array but at the end you attempt to set orderCart.subtotal etc...
Change your helper to have a separate summary object:
var summary = {};
summary.subtotal = total;
summary.tax = summary.subtotal * .23;
summary.total = summary.subtotal + summary.tax;
return {items: orderCart, summary: summary}
Then in your html do:
{{#each orderitems.items}}
...
{{/each}}
Finally in your summary line use {{currency orderitems.summary.tax}} etc...
Your values are rendered as NaN because orderCart is undefined.
You could define a separate helper to fix your code:
Template.order.helpers({
orderItems: function () {
return OrderItems.find().map((orderItem) => {
let product = Products.findOne({
_id: orderItem.product
});
if (product) {
orderItem.productname = product.description;
orderItem.price = calcPrice(product, orderItem);
return orderItem;
}
});
},
orderCart: function () {
let orderCart = {subtotal: 0};
OrderItems.find().forEach((orderItem) => {
let product = Products.findOne({
_id: orderItem.product
});
if (product) orderCart.subtotal += calcPrice(product, orderItem);
});
orderCart.tax = orderCart.subtotal * .23;
orderCart.total = orderCart.subtotal + orderCart.tax;
return orderCart;
}
});
function calcPrice(product, orderItem) {
return (Number(product.price) * orderItem.qty);
}
<template name="order">
<div class="page-header">
<h1>
<small>My Order</small>
</h1>
</div>
<table class="span4 table table-striped table-bordered table-hover">
<thead>
<th>Qty</th>
<th>Product</th>
<th>Price</th>
<th></th>
</thead>
<tbody>
{{#each orderItems}}
<tr>
<td>{{qty}}</td>
<td>{{productname}}</td>
<td>{{currency price}}</td>
<td><span class="label-important label removeci">X</span></td>
</tr>
{{else}}
<tr>
<td colspan="3">No Products in Order</td>
</tr>
{{/each}}
{{#with orderCart}}
<tr>
<td class="totalcol" colspan="2">SubTotal:</td>
<td colspan="2">{{currency orderCart.subtotal}}</td>
</tr>
<tr>
<td class="totalcol" colspan="2">Tax 6%:</td>
<td colspan="2">{{currency orderCart.tax}}</td>
</tr>
<tr>
<td class="totalcol" colspan="2">Total:</td>
<td colspan="2">{{currency orderCart.total}}</td>
</tr>
{{/with}}
</tbody>
</table>
</template>
Please note: I noticed a lot of missing semicolons. I strongly recommend to fix that, as this may cause several issues on deployment due to Meteor's minifying process.

Can't fetch single record in Angular js/HTML

Hope you are doing good..
I'm trying to fetch single record from datasource by Id in UI via Angular-js.
Using Web-API for retrieving values from DB.
To make it simple : HTML-->Angular-->WebAPI-->DB
When i'm trying it says Id passed is Null..Don't know how to rectify.
hope i've missed to fill hole in somewhere....below snippets fr ref.
(Also can u verify/correct me the way i've coded in html is right way to display values fetched by Id)
HTML :
<div ng-controller="SingleController">
<input type="text" ng-model="_Id" />
<input type="button" value="search" ng-click="search()" />
<table>
<tr>
<td>MovieId</td>
<td>{{MovID}}</td>
</tr>
<tr>
<td>Title</td>
<td>{{Movtitle}}</td>
</tr>
<tr>
<td>Genre</td>
<td>{{Movgnre}}</td>
</tr>
<tr>
<td>Classification</td>
<td>{{Movcls}}</td>
</tr>
<tr>
<td>ReleaseDate</td>
<td>{{Movdate}}</td>
</tr>
<tr>
<td>Rating</td>
<td>{{Movrate}}</td>
</tr>
<tr>
<td>Cast</td>
<td>{{Cast}}</td>
</tr>
</table>
</div>
Controller.JS
app.controller('SingleController', function ($scope, MyService) {
var Id = $scope._Id;
$scope.search = function (Id) {
var promiseGetSingle = MyService.getbyId(Id);
promiseGetSingle.then(function (pl) {
var res = pl.data;
$scope.MovID = res._movieId;
$scope.Movtitle = res._title;
$scope.Movgnre = res._genre;
$scope.Movcls = res._classification;
$scope.Movdate = res._releaseDate;
$scope.Movrate = res._rating;
$scope.Cast = res._cast;
// $scope.IsNewRecord = 0;
},
function (errorPl) {
console.log('failure loading Employee', errorPl);
});
}
});
service.js
this.getbyId = function (Id) {
return $http.get("/api/values/" + Id);
};
Please ignore this lengthy snippets.
Could you please help me on this.
Your search function is expecting you to pass a value when it is invoked on ng-click:
<input type="button" value="search" ng-click="search(_Id)" />

Angular, view not updating when changing model

I'm changing a model and I was expecting the view to update but it isn't:
Here is my view:
<div ng-controller="showCarCtrl">
<h1>Damaged Cars</h1>
<table border="1">
<tr>
<th>Plate Number</th>
<th>Brand</th>
<th>Color</th>
</tr>
<tr ng-repeat="car in cars" ng-show="car.damaged">
<td>{{car.plate_number}}</td>
<td>{{car.brand}}</td>
<td>{{car.color}}</td>
<td>
<button ng-click="setRepaired(car.cid)">Repaired</button>
</td>
</tr>
</table>
</div>
Here is the controller:
app.controller('showCarCtrl', function($scope, $rootScope,CarService){
$scope.setDamaged = function(cid){
console.log("setting the car as damaged "+cid)
$rootScope.loading = true;
CarService.setDamageCar(cid)
.then(function(data){
$rootScope.loading = false;
console.log("set damage 1")
for(var i=0; i<$scope.cars.length; i++) {
console.log("setting car as damage");
if ($scope.cars[i]==cid) {
$scope.cars[i].damaged = 1
$scope.$apply();
console.log("it enters here");
break;
}
console.log($scope.cars)
}
},
//deferred
function(data){
console.log('Car Service failed');
$rootScope.loading = false;
});
};
});
I've checked from the server, the reply from the server is properly comming and I'm successfully updating the model at $scope.cars[i].damaged = 1, the only issue is that I was expecting the view to change because as shown above, in the view, I've something as <tr ng-repeat="car in cars" ng-show="car.damaged">, but the view is not updating
I think you have an error in your code here:
if ($scope.cars[i]==cid) {
Maybe it should be like this:
if ($scope.cars[i].cid === cid) {

Categories