Reputation:
I'm developing an angular application where the main page loads 1000 images, but the user can only look at 20 at a time. I will also have several filters on my list, so that it can be filtered and sorted based on different criteria.
I've tried http://binarymuse.github.io/ngInfiniteScroll/# and http://ngscroller.herokuapp.com/ but neither seems to work that well.
Ngscroller does work but it breaks when I try to apply my filters. I also prefer this one since it does not require me to include jquery. Are there any simple directives out there that can do what I need to? I'm trying to speed up my web page but I don't want to reinvent the wheel if there is something out there which already accomplishes this.
Here is my attempt with ngScroller: http://plnkr.co/edit/r0uhV3OxT2USxmrBQk22?p=preview
<div class="content" ng-controller="MainController" ng-scroller="content">
<ul class="list" ng-scroller-repeat="item in items | filter:idOver500k | orderBy:predicate:!reverse">
<li class="item">{{item.text}}</li>
</ul>
</div>
The scroll works without the filter and orderBy, but I'm looking for a method that will handle all cases.
It takes at least 3 seconds longer to load my page than it does if I remove the images. It looks like angular is loading only when all of the images are obtained. What is the best way to handle this?
Thank you!
Upvotes: 6
Views: 5998
Reputation: 43526
Demo with ng-infinite-scroll: http://plnkr.co/edit/O5w0Fp
ng-infinite-scroll has different mechanism with ng-scroller. infinite-scroll will trigger a loadMore
function when user scroll to the bottom. You can define loadMore
function yourself.
I created a lazyLoad
filter to only only return part of the filtered items, managed by counter
variable. When scroll to the bottom, counter
will be incremented by one to return more items from lazyLoad
filter.
When user change the order by parameter, counter
will be reset to 1.
When counter
equals 1
, it will load the first 30 items.
It may have problem if the height of document.body
is less than the height of window
, because that way document will not be able to scroll thus will not trigger scroll
event. You have to manually check the heights and trigger loadMoreItems
accordingly.
The problem will occur while page initialize or counter
reset.
I added adjustCounter
function to run after reset the counter. ng-infinite-scroll will handle this when page load internally.
Upvotes: 9
Reputation: 27632
Looks like this isn't going to work with a dynamic filter without fixing ngScroller.
The offending code seems to be in the ng.Scroller.prototype.compile
function:
var exp = carousel.getAttribute('ng-scroller-repeat');
var keys = exp.split(/\s+in\s+/);
Where ngScroller basically splits the attribute without looking at filters or the like.
One possibe workaround is like @Daiwei suggests and filter before binding. Not such a bad solution as this is a lot faster anyway.
app.controller('MainController', function ($scope) {
$scope.allItems = generateItems(1000);
$scope.items = $scope.allItems.reduce(function(previous, item){
if (item.id > 500000)
{
previous.push(item);
}
return previous;
},[]);
});
See this Plunker for an example.
Upvotes: 0