I've an array of string, I need to display it using ng-repeat of AngularJS like the following screenshot:
I have an idea, to "play" in the index-s to display that:
<tbody ng-repeat="param in params">
<tr>
<td>{{param.name}}</td>
</tr>
</tbody>
That for every row I'll display the first item, and to display in the same row every ( $index, $index + 3, $index + 6)
Is there any other ideas, or an idea how to do that?
You can do something like this:
http://jsfiddle.net/cmdm1dhL/1/
<div ng-controller="MyCtrl">
<table>
<tr ng-repeat="row in [] | range:Math.ceil(items.length/tableColumns)">
<td ng-repeat="item in items | everyNth:row:Math.ceil(items.length/tableColumns)">{{item}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
var myApp = angular.module('myApp',[]);
myApp.filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++)
input.push(i);
return input;
};
});
myApp.filter('everyNth', function() {
return function(input, row, nth) {
var output = [];
for (var i=row; i<input.length; i+=nth)
output.push(input[i]);
return output;
};
});
function MyCtrl($scope) {
var numberOfItems = 14;
$scope.items = [];
for (var i=1; i<=numberOfItems; i++)
$scope.items.push('Item ' + i);
$scope.tableColumns = 3;
$scope.Math = window.Math;
}
</script>
Related
I have an application which displays a table (xeditable) by retrieving data from a mySQL database.
The database table which displays the content constantly changes in the background and I am trying to figure out how I can reflect those changes in the UI without refreshing the page or the entire table each time a change was made in the database.
Basically, I would like to "push" the changes to the view and a change has been detected in the database.
I understand that is not available with PHP/MySQL so I guess there must be a way around it by using either a 3rd party library or even a mid tier nodeJS...
I read on google's firebase (with ReactJS) how this can be achieved OTB and thought it may be possible to do without rewriting my entire app.
Any thoughts?
snippets of my current codebase:
app.js
var app = angular.module('myApp', ['ui.bootstrap','countTo','xeditable']);
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.filter('abs', function () {
return function(val) {
return Math.abs(val);
}
});
app.run(function(editableOptions) {
editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
});
app.config(['$compileProvider', function($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|http?|file|data):/);
}]);
app.controller('customersCrtl', function ($scope, $http, $timeout, $interval, $window) {
var init = function loadItems(){
$scope.$emit('LOAD');
$scope.progressBar = { progress : 0 };
$http.get('ajax/getItems.php').success(function(data){
$scope.list = data;
$scope.updateID = data.updateID;
$scope.currentPage = 1; //current page
$scope.entryLimit = 50; //max no of items to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
$scope.priceInfo = {
min: 0,
max: 100000
}
$scope.$emit('UNLOAD');
var array = $scope.list;
var flags = [], output = [], l = array.length, i;
for(i=0; i<l; i++) {
if( flags[array[i].category]) continue;
flags[array[i].category] = true;
output.push(array[i].category);
}
var array_manufact = $scope.list;
var flags = [], output_manufact = [], l = array_manufact.length, i;
for( i=0; i<l; i++) {
if( flags[array_manufact[i].manufacturer]) continue;
flags[array_manufact[i].manufacturer] = true;
output_manufact.push(array_manufact[i].manufacturer);
}
$scope.cats = output;
$scope.manufact = output_manufact;
//console.log($scope.cats);
});
(function progress(){
if($scope.progressBar.progress < 100){
$timeout(function(){
$scope.progressBar.progress += 1;
progress();
},5);
}
})();
index.html:
<html>
<tbody>
<tr ng-repeat="data in filtered = (list | filter:search | filter:{category:by_cat} | filter:{notes:by_notes} | filter:{Locked:by_search_locked} | filter:{external_link:by_external_link} | filter:{name:by_name} | filter:{cat2:by_cat2} | filter:{errorStatus:search`enter code here`_status} | filter:{error_status:search_status_opt} | orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit" ng-class="{'success' : data.error_status=='--example1--', 'warning' : data.place_1_name!='my_stock', 'danger' : data.error_status == 'not loaded'}">
<td ng-class='{red : data.Locked==1}'><center>{{data.ID}}</center></td>
<td ng-class='{red : data.Locked==1}'><center>{{data.name}}</center></td>
<td ng-class='{red : data.Locked==1}'>
<center>
cat: {{data.category}}
<br/>
cat2: {{data.category2}}
</center></td>
<td ng-class='{red : data.Locked==1}'><center>{{data.price}}</center></td>
<td ng-class='{red : data.Locked==1}'><center>
<div ng-if="data.notes.length > 0">
<div ng-repeat="i in data.notes">
<b><font color="red">{{i}}</font></b>
</div>
</div>
<div ng-if="data.notes.length==0">
---
</div>
</center>
</td>
<td ng-class='{red : data.Locked==1}'>
<center>
<div ng-if="data.minPrice !=''">
<a href="#" editable-text="data.minPrice" onbeforesave="updateMinPrice(data.productID,$data)">
<font class='green'>{{data.minPrice}}</font>
</a>
<span ng-if="data.minPrice_last_changed!='---'">
<br/>
<br/>
LastChangedON: <font dir="ltr">{{data.minPrice_last_changed}}</font>
</span>
</div>
<div ng-if="data.minPrice == '' ">
<div editable-text="data.minPrice" onbeforesave="updateMinPrice(data.productID,$data)">
<font class='orange'>click to add</font>
</div>
</div>
</center></td>
</html>
Use the $interval1 service to poll your endpoint
app.controller('MainCtrl', function($scope, $http, $interval) {
$interval(function(){
$http.get('/api/metrics').then(function(res){
$scope.data = res.data;
});
},5000);
});
Here is a plunker simulating polling an endpoint with $interval
https://docs.angularjs.org/api/ng/service/$interval
Here why my total amt not counting
<div ng-controller="MyHomeCNtrls">
<div id="CountdataWithinhTheDiv">
<table>
<tr>
<td>Id</td>
<td>Name</td>
<td>Quentity</td>
<td>Price</td>
<td>Total</td>
</tr>
<tr ng-repeat="pr in Prodt">
<td>{{pr.productId}}</td>
<td>{{pr.ProductName}}</td>
<td>{{pr.quantity}}</td>
<td>{{pr.Price}}</td>
<td>{{pr.Total}}</td>
<td>Total: {{ getTotal() }}</td>
</tr>
</table>
</div>
</div>
AngularCode
Service
this.Gymser = function () {
var xx = $http({ url: '/Home/Prodt', method: 'Get',params: JSON.stringify(),
content: { 'content-type': 'application/Json' } }) return xx;}
controller
function PropertyData() {
var xxx = Myservice.Gymser();
xxx.then(function (d) {
$scope.Prodt = d.data;
})
}
AngularCode For Counting
$scope.getTotal = function () {
var total = 0;for (var i = 0; i < $scope.Products.length; i++) {
var product = $scope.Products[i];total += (Product.price * Product.quantity);}return total;}
I do not see your controller having Function named getTotal()
You should have defined in the controller,
$scope.getTotal = function(type) {
var total = 0;
angular.forEach($scope.items, function(el) {
total += el[type];
});
return total;
};
DEMO
I 'm a beginner in AngularJS. I have created a page that retrieves records from database along with total records using an Ajax call. After populating the grid with the records, I wanted to refresh the pager control based on values received from the Ajax call such as the total records and the current page number as 1. I'm seeing the pager but is not refreshed. Can you please verify and let me know what I'm missing here?
var angularPersonModule = angular.module("angularPersonModule", ['ui.bootstrap']);
angularPersonModule.controller("AngularPersonController", AngularPersonController);
angularPersonModule.controller("PaginationController", PaginationController);
angularPersonModule.factory("PaginationService", PaginationService);
PaginationController.$inject = ['$scope', '$timeout', '$rootScope', 'PaginationService'];
function PaginationController($scope, $timeout, $rootScope, PaginationService) {
$scope.setPage = function(pageNo) {
if ($scope.currentPage === pageNo) {
return;
}
$scope.currentPage = pageNo;
$rootScope.$broadcast("personPageChanged", $scope.currentPage);
alert("call from setPage");
};
$scope.pageChanged = function() {
var i = 0;
};
$scope.$on('personRefreshPagerControls', function(event, args) {
//the solution:
setTimeout(function() {
//setTimeout is a deffered call (after 1000 miliseconds)
$timeout(function() {
$scope.totalItems = PaginationService.getTotalRecords();
$scope.currentPage = PaginationService.getPageNumber();
$scope.itemsPerPage = PaginationService.getPageSize();
$scope.numPages = PaginationService.getPageCount();
alert("totalItems = " + $scope.totalItems);
alert("currentPage = " + $scope.currentPage);
alert("itemsPerPage = " + $scope.itemsPerPage);
alert("pageCount = " + $scope.numPages);
});
}, 900);
});
}
AngularPersonController.$inject = ['$scope', '$rootScope', 'AngularPersonService', 'PaginationService'];
function AngularPersonController($scope, $rootScope, AngularPersonService, PaginationService) {
$scope.getAll = function() {
$scope.persons = AngularPersonService.search();
PaginationService.setTotalRecords(3);
PaginationService.setPageNumber(1);
PaginationService.setPageSize(2);
PaginationService.setPageCount(2);
$rootScope.$broadcast("personRefreshPagerControls", 3);
}
$scope.$on('personPageChanged', function(event, args) {
alert("pageChanged Event fired");
alert("Received args = " + args);
$scope.getAll();
});
$scope.getAll();
}
function PaginationService() {
var currentPage = 1;
var pageCount = 2;
var pageSize = 2;
var totalRecords = 3;
return {
getPageNumber: function() {
return currentPage;
},
setPageNumber: function(pageNumber) {
currentPage = pageNumber;
},
getPageSize: function() {
return pageSize;
},
setPageSize: function(newPageSize) {
pageSize = newPageSize;
},
getTotalRecords: function() {
return totalRecords;
},
setTotalRecords: function(newTotalRecords) {
totalRecords = newTotalRecords;
},
getPageCount: function() {
return pageCount;
},
setPageCount: function(newPageCount) {
pageCount = newPageCount;
}
}
}
angularPersonModule.factory("AngularPersonService", function($http) {
return {
search: function() {
return [{
"Name": "Hemant"
}, {
"Name": "Ashok"
}, {
"Name": "Murugan"
}];
}
}
});
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-resource.min.js"></script>
<script src="https://raw.github.com/angular-ui/bootstrap/gh-pages/ui-bootstrap-0.14.3.js"></script>
<script src="https://raw.githubusercontent.com/angular-ui/bootstrap/gh-pages/ui-bootstrap-tpls-0.14.3.js"></script>
<div ng-app="angularPersonModule">
<div class="panel panel-default">
<div class="panel-body" ng-controller="AngularPersonController">
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="col-md-3">
Name
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="person in persons">
<td>
<span>{{person.Name}}</span>
</td>
</tbody>
</table>
</div>
</div>
<div ng-controller="PaginationController">
<uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination>
</div>
</div>
Update
Now I have updated the snippet so that you can execute and see the result manually.
I'd like to implement pagination with AngularJS but I have some problems.
I don't know how to update the $scope.agreements object when clicking on a new page...
var app = angular.module("GestiawebApp", []);
app.controller("AgreementsController", function($scope, $http) {
var nbPages, limit;
$http.get('/api/agreement').success(function(data, status, headers, config) {
limit = data.limit;
nbPages = Math.ceil(data.agreements.length/data.limit);
$scope.agreements = data.agreements.slice(0, limit);
});
$scope.getPages = function() {
var pages = [];
for (var i = 1; i <= nbPages; i++) {
pages.push(i);
}
return pages;
};
$scope.goToPage = function(page){
// simple test to change the agreements, but it seem's not working
$scope.agreements = $scope.agreements.slice(page*limit, (page*limit)+limit);
};
});
<!-- Loop -->
<tr ng-repeat="agreement in agreements | filter:search">
<td>{{agreement.number}}</td>
<td>{{agreement.reference}}</td>
<td>
{{agreement.billbook.capital}} €
</td>
</tr>
<!-- End loop -->
<!-- Paginaiton -->
<ul>
<li ng-repeat="i in getPages() track by $index" ng-click="goToPage($index+1)">{{$index+1}</li>
</ul>
<!-- End pagination -->
You should store all agreements data in a variable to use for paginating
$scope.allAgreements = [];
$http.get('/api/agreement').success(function(data, status, headers, config) {
limit = data.limit;
nbPages = Math.ceil(data.agreements.length/data.limit);
$scope.allAgreements = data.agreements; //new change
$scope.agreements = $scope.allAgreements.slice(0, limit);
});
$scope.goToPage = function(page){
// simple test to change the agreements, but it seem's not working
$scope.agreements = $scope.allAgreements.slice(page*limit, (page*limit)+limit);
};
HTML Code
<body ng-app="MyApp">
<div ng-controller="PaginationCtrl">
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in pagedItems">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
</tr>
</tbody>
<tfoot>
<td colspan="3">
<div class="pagination">
<ul>
<li ng-class="prevPageDisabled()">
<a href ng-click="prevPage()">« Prev</a>
</li>
<li ng-repeat="n in range()" ng-class="{active: n == currentPage}" ng-click="setPage(n)">
{{n+1}}
</li>
<li ng-class="nextPageDisabled()">
<a href ng-click="nextPage()">Next »</a>
</li>
</ul>
</div>
</td>
</tfoot>
</table>
</div>
</body>
Javascript
var app = angular.module("MyApp", []);
app.factory("Item", function() {
var items = [];
for (var i=0; i<50; i++) {
items.push({ id: i, name: "name "+ i, description: "description " + i });
}
return {
get: function(offset, limit) {
return items.slice(offset, offset+limit);
},
total: function() {
return items.length;
}
};
});
app.controller("PaginationCtrl", function($scope, Item) {
$scope.itemsPerPage = 20;
$scope.currentPage = 0;
$scope.range = function() {
var rangeSize = 5;
var ret = [];
var start;
start = $scope.currentPage;
if ( start > $scope.pageCount()-rangeSize ) {
start = $scope.pageCount()-rangeSize;
}
for (var i=start; i<start+rangeSize; i++) {
ret.push(i);
}
return ret;
};
$scope.prevPage = function() {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};
$scope.prevPageDisabled = function() {
return $scope.currentPage === 0 ? "disabled" : "";
};
$scope.nextPage = function() {
if ($scope.currentPage < $scope.pageCount() - 1) {
$scope.currentPage++;
}
};
$scope.nextPageDisabled = function() {
return $scope.currentPage === $scope.pageCount() - 1 ? "disabled" : "";
};
$scope.pageCount = function() {
return Math.ceil($scope.total/$scope.itemsPerPage);
};
$scope.setPage = function(n) {
if (n > 0 && n < $scope.pageCount()) {
$scope.currentPage = n;
}
};
$scope.$watch("currentPage", function(newValue, oldValue) {
$scope.pagedItems = Item.get(newValue*$scope.itemsPerPage, $scope.itemsPerPage);
$scope.total = Item.total();
});
});
Heres the fiddle.
http://jsfiddle.net/go14nac5/
When the itemsPerPage is 5 or 10 the pagination works fine but when the itemsPerPage is changed to 20 or more. The pagination has a problem, where the page numbers are displayed with negative values and zero.
Can someone help me sort this out to make a robust bootstrap pagination?
Modify range function:
$scope.range = function() {
var rangeSize = 5;
var ret = [];
var start;
start = $scope.currentPage;
if ( start > $scope.pageCount()-rangeSize ) {
start = $scope.pageCount()-rangeSize;
if (start < 0) {
start = 0;
}
}
for (var i=start; i<start+rangeSize && i < $scope.pageCount(); i++) {
ret.push(i);
}
return ret;
};