Right now infinite scroll only supports the parameter distance
as the percentage scrolled to the bottom. How do you do this for percentage scrolled to the top? This is essential for chat-style scrolls where you load more chat history as the User scrolls to the top. Anyone? hacks?
I ditched the infinite scroll and went with this simple solution:
// Controller
$scope.loadMore = function() {
// fetch data here...
};
$scope.onChatScroll = ionic.debounce(function(top) {
if ($ionicScrollDelegate.getScrollPosition().top <= top) {
$scope.loadMore();
}
}, 500);
// View
<ion-scroll on-scroll="onChatScroll(10)">
<ion-list>
<ion-item ng-repeat=""></ion-item>
</ion-list>
</ion-scroll>
Take note on the use of ionic.debounce
to trigger that callback once in 500ms.
@deanq: Iāve started using your solution for my own chat-based app, but do you have any advice on how to keep the scroll position from sticking to the top when you load more items to the list? The problem I am having it is that the scroll position when you are near the top is between 0 and 10 (or whatever you pass in to the onChatScroll()
function). When new items are added to the front of the array, the scroll position still stays at the top of the view, which means now Iām looking at the top of all the new items instead of where I want to be, still at the bottom of the new itemsā¦
does this make sense?
I know the issue youāre talking about. I didnāt explore much solutions around it. I managed that by providing less historical rows. For example, if the height of the view is good for 10 chat histories, I would only return 9 per page. So every time more history is loaded per scrolling up, the user would still be able to see the last item at the bottom. You have to ask yourself, how much history per page is appropriate here?
Another avenue I was looking atābut didnāt continue pursuingāwas $ionicScrollDelegate.anchorScroll(). My strategy was to put an anchor to every chat row, and take note of the last anchor of the new page that is being loaded. Then after the loadMore, I could just trigger anchorScroll without animation. Thereās a weird catch to using anchorScroll though, so read up on that.
Iāve figured out a solution that worksā¦ it isnāt pretty, but it works for now. I have a button at the top of my chat history as long as there are more messages to fetch. When the view first loads and I call $ionicScrollDelegate.scrollBottom();
I also store the content height, eg: var contentHeight = document.getElementById(āchat-contentā).scrollHeight;
When new data is loaded, I wait little bit ($timeout of say 100ms) and then grab the new chat-content scrollHeight. I then call $ionicScrollDelegate.scrollTo(0, newHeight - oldHeight, false);
It can be a little jumpy, but at least it works, and Iām not trying to load 1000ās of messages at once. As for your initial suggestion, I unfortunately cannot just load a set amount of history per page as each item is variable in height. Some items take up most of the screen on their own, sometimes you can see several messages at once.
I know other apps in the wild do this without having the scroll issue. Slack is one of them. To me it seems there must be a way to freeze the content div (turn off scrolling? something with overflow? I am not sure), add the new items to the array, turn on scrolling, and resize for the new size of the content.
Anything new about this ? I need exactly the same functionnality !
Iām also looking for a smoother solution to this. I need to keep the scrolling position stay in the same location after adding items on top the list.
As @cquartier described, Iām using same temporary solution which is not completely satisfactory but works :
if (scroller.getScrollPosition().top <= 20) { // larger the value results in more jerky list
lastScrollHeight = document.getElementById('full-message-list').scrollHeight;
pullPreviousMessages();
$timeout(function(){ // adding some delay to load the scroller with new items
var currentScrollHeight = document.getElementById('full-message-list').scrollHeight;
var lastPostion = currentScrollHeight - lastScrollHeight;
scroller.scrollTo(0, lastPostion, false);
}, 300);
}
Also, the above function is attached to the scroller element using following code :
<ion-content id="full-message-list" delegate-handle="full-message-list" on-scroll="onMesaageScroll()" scroll-event-interval="50">
@BeRMaNyA , did you modify the ionic lib code ? Could you please elaborate
Seems that there is still no official way to do it from top?
Wow I think this is such an important feature that Ionic should include to their core. Many people (include me) need it
same issue here please anyone help usā¦!
This seems like a problem thats too difficult for every developer to write his own solution for. It would be really cool if the infinite scroll would account for this scenario.
Thanks for this solution! I found for me performance is better without āionic.debounceā. I assume the on-scroll event already has some debouncing built in because I only see a reasonable number of events being fired.
I everyone,
Iām facing same issue and tried solutions using timeouts but itā's not really stableā¦Iāll try tomorow the following option:
-
create a directive and insert to the dom just before the first item of ng-repeat with a callback function like this
-
create another directive but this time insert it after the last item of ng-repeat with a callback fuction to restaure scroll to originial position
<div ng-if="$index===$last" ng-init="restaureScrollPosition()"saveScrollPosition function(){ lastScrollHeight = document.getElementById('full-message-list').scrollHeight; } restaureScrollPosition function(){ var currentScrollHeight = document.getElementById('full-message-list').scrollHeight; var lastPostion = currentScrollHeight - lastScrollHeight; scroller.scrollTo(0, lastPostion, false); }
I donāt see how to get closer to the dom rendering the process
Also running into the same issue, tried above solutions but its not really solid ā¦ any progressive ionic team?
Thanks
A
+1 ion infinite scroll to the top
You can check my solution: