ui-bootstrap pagination items-per-page not changing page size - angularjs

I hate asking this question, because it seems like all pagination questions have been answered. However, I do not follow what is making the pagination pages shorten. I believe that my example is very similar to other examples.
I am getting the correct number of tabs, current page is changing correctly as well. However, the length is not matching the assigned items-per-page limit.
Here is my controller
viewsModule.controller('CountryCtrl', ['$scope', 'cacCountries', function($scope, cacCountries) {
$scope.loading = true;
$scope.countries = [];
$scope.currentPage = 1;
$scope.itemsPerPage = 20;
$scope.maxSize = 20;
cacCountries().then(function(countries) {
// console.log(countries);
$scope.loading = false;
$scope.countries = countries;
$scope.totalItems = countries.length;
});
}]);
I have set my itemsPerPage to 20
In my html I made sure to reference the itemsPerPage
<pagination
total-items="totalItems"
items-per-page= "itemsPerPage"
ng-model="currentPage"
class="pagination-sm">
</pagination>
I am getting back 13 tabs for 250 objects in the array. However, all 250 objects are showing up. I am expecting 20 per page.
The ng-repeat is plain
<tr ng-repeat="country in countries |filter:search ">
What could I be missing that would bind current page?

The pagination directive gives you a way to present to the user the list of selectable pages based on the size of the data and other parameters, and lets the user easily control the current page.
It does not actually filter the data for you. You still have to apply the itemsPerPage, currentPage etc within your ng-repeat.
One way to do this is to add an additional filter to help with skipping
app.filter('offset', function() {
return function(input, start) {
return input.slice(start);
};
})
and then use this with limitTo to control the paging
<div ng-repeat="country in countries | filter:search | offset: (currentPage - 1) * itemsPerPage | limitTo:itemsPerPage">
{{country.name}}
</div>
JSFiddle here

Old question.. but it worth to answer with the simple method.
<tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) ">
Fork JSFiddle from #sheilak

Related

IONIC: unable to load dynamic content in `ion-infinite-scroll`

I am new with ionic framework.Currently i am working on ionicsidemenu app.
I have 100 plus records i want to display 20 records at once. When scroll down get next 20 records. For this i am using ion-infinite-scroll but i am unable to understand how to call next 20 records. I am using webservice for fetching records.
Please help me.
You have to use array instead of object in this case because pushing items in array is easier than pushing into object. Ionic documentaton also uses array in their example.
View:
<div ng-repeat="item in data">...</div>
<ion-infinite-scroll (ionInfinite)="getData()">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Controller:
$scope.data = [];
var page = 1;
$scope.getData = function(){
$http.get('http://example.com?page='+page).then(function(response){
page++;
$.each(response,function(key,item){
$scope.data.push(item);
});
}, function(error){
});
}
When scroll reach to ion-infinite-scroll function will called. at beginning there is no data on screen so without scrolling ion-infinite-scroll function called automatically to load first page.
use limitTo together with Infinite scrolling. AngularJS ng-repeat offers from version 1.1.4 the limitTo option. I slightly adapted the Infinite Scroll directive to make scrolling within a container possible that does not have height 100% of window.
ng-repeat="item in items | orderBy:prop | filter:query | limitTo:limit"
Notice that limit is a variable in the $scope, so changing it automatically adjusts the number of rendered items. And incrementing limit, only renders the added elements.
<table>
<tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>
//the controller
$scope.totalDisplayed = 20;
$scope.loadMore = function () {
$scope.totalDisplayed += 20;
};
$scope.data = data;
or try out this solution
<body>
<pane ng-controller="MainCtrl">
<header-bar title="'Infinite Scroll Example'">
</header-bar>
<content has-header="true" padding="true" on-infinite-scroll="addMoreItem">
<div class=" list padding">
<div ng-repeat="item in items | limitTo:numberOfItemsToDisplay" class="item" type="item-text-wrap">
<h3>{{item}}</h3>
</div>
</div>
</content>
</pane>
</body>
js code
angular.module('myApp', ['ionic'])
.controller('MainCtrl', function($scope) {
$scope.numberOfItemsToDisplay = 20; // number of item to load each time
$scope.items = getData();
function getData() {
var a = [];
for (var i=1; i< 1000; i++) {
a.push(i);
}
return a;
}
$scope.addMoreItem = function(done) {
if ($scope.items.length > $scope.numberOfItemsToDisplay)
$scope.numberOfItemsToDisplay += 20; // load 20 more items
done(); // need to call this when finish loading more data
}
});
while on scrolling will display 20 items.

Progressive scrolling with angularjs

I have a database witch contains 1000 products. I have a list which displays 10 products at one time. This grid is scrollable. I want to load products 10 by 10.
What is the best way to do this with angularjs ? I am looking for a method which need shortest code.
Thanks
The concept is called pagination and if you want to achieve this in less amount of time then you must go for any already available module.
I have used Infinite Scroll It is very easy to use and would help you to implement things in no time.
You are looking for lib called "infinite scroll". You can find this app here https://github.com/ifwe/infinite-scroll
Where in the controller you put this code:
var app = angular.module('MyApp', ['tagged.directives.infiniteScroll']);
app.controller('MainController', ['$scope', '$http', function($scope, $http) {
$scope.page = 1;
$scope.items = [];
$scope.fetching = false;
// Fetch more items
$scope.getMore = function() {
$scope.page++;
$scope.fetching = true;
$http.get('/my/endpoint', { page : $scope.page }).then(function(items) {
$scope.fetching = false;
// Append the items to the list
$scope.items = $scope.items.concat(items);
});
};
}]);
And this is your view:
<div ng-app="MyApp">
<div ng-controller="MainController">
<ul tagged-infinite-scroll="getMore()">
<li ng-repeat="item in items">
{{ item.title }}
</li>
</ul>
</div>
</div>
Once it detect you scroll is at the end of the ng-repeat items it calls getMore function to load new items. Remember to add to the endpoint limit, and offset to load rest of the data, not same data every time.

Angular Updates Model but no Two Way Binding w/ Custom Filter

I recently wrote a simple custom filter which only displays items in my model given a specific model property and it works great. It is below..
Filter
app.filter('status', function() {
return function(input, theStatus) {
var out = [];
for (var i = 0; i < input.length; i++) {
var widget = input[i];
if (widget.status === theStatus)
out.push(widget);
}
return out;
};
});
The filter is applied as such on an ng-repeat.
<tr ng-repeat="widget in pendingWidgets = (widgetList | status: 0)">
<td><span class="glyphicon glyphicon-usd" /></td>
<td><span class="glyphicon glyphicon-usd" /></td>
<td><span class="glyphicon glyphicon-usd" /></td>
<td><span class="glyphicon glyphicon-usd" /></td>
</tr>
And on a panel heading as so
<div class="panel-heading"><span class="badge">{{pendingWidgets.length}}</span></div>
When the glyph is clicked ng-click runs updateStatus() as below...
$scope.updateStatus = function(theId, newStatus) {
widgets.setStatus(tagNumber, newStatus);
$scope.displayAlert = true;
};
And the widget.setStatus() is as such..
app.factory('widgets', ['$http', function($http) {
var o = {
widgets:[]
};
o.setStatus = function(aWidget, theStatus) {
return $http.put('/widgets/' + aWidget, { 'status': theStatus }).success(function (data) {
// do I need to put something here?
});
};
return o;
}]);
My question lies in
How can I get my page to refresh on the ng-click action when the updateStatus() call is made on my model? When the glyph is clicked the model is updated but the page is not. Only on a page refresh or when I visit a different page and then come back does the page display the updated model accurately with respect to the custom filter.
It doesn't look like you're updating the status for a particular widget (on the client side). You're telling your server about the update, but on the client side, no update happens.
That's why when you refresh (i imagine you're loading the widgets from the db / backend) you see the update.
Where you have: // do I need to put something here? you need to do something like:
aWidget.status = data.status; // where data is the updated widget object
(this assumes that your backend is returning the updated widget - which if you're following the same conventions that I'm used to - it should be).

Angular with filter in different view

I have a question concerning Angular and Angular-UI Router. I would like to place a filter in a bootstrap navbar which can vary depending on the current route. I have tried to implement this behaviour with Angular-UI Router but ui-router doesn't support sharing the same controller across multiple views. In their documentation the touch on this topic. See: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views.
I have created a plunker with the desired behaviour: http://plnkr.co/edit/W0UgeW
Onto my question: Is there any way I can accomplish this behaviour? I dont necissarly want to do it with Angular-ui Router, if it's at all possible without using extensions I would prefer to do it that way.
Thank you,
Bart
You can create custom filter like:
myapp.filter('myfilter', function() {
return function( items, combo) {
var filtered = [];
console.log(items, combo);
angular.forEach(items, function(item) {
if(item.name == combo){
filtered.push(item);
}
});
return filtered;
};
});
Now to pass combo option to view we can write:
$rootScope.theFilter = '';
Our table will look like:
<table id="searchTextResults">
<tr><th>Name</th><th>Phone</th></tr>
<tr ng-repeat="friend in friends | myfilter:theFilter">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
</tr>
</table>
See Demo Plunker

How to change a $scope variable inside a filter

I need to change a $scope variable inside a filter. The $scope variable is used for a ng-show attribute and the information is only acceded in the filter because I have a ng-repeat with some information and applied by some filters and I need to know when the filters delete all my result to show a message... here is an example: (this is only an idea)
.controller("thing", function() {
$scope.showText = false;
})
.filter("filterText", function() {
return function(information) {
if (information == "") { /* NEED TO CHANGE $scope.showText to true */ }
}
})
HTML:
<div ng-view="showText"> Some Text here </div>
<div ng-repeat="info in information | filterText"></div>
Thanks.
I agree with the comments that you probably don't want to be changing data in the filter in the first place but if you were really hard pressed you might be able to achieve this by just defining a filter function inside your controller (rather than an actual angular "filter") and then just use it as such:
ng-repeat="item in items | filter:myFilter()"
$scope.myFilter = function(item) {
// access to scope here
}
Jeff's code have small error: we need pass only function name to filter as below
ng-repeat="item in items | filter:myFilter"
$scope.myFilter = function(item) {
// access to scope here
}

Resources