Ionic chatapp, load the most recent thread at the bottom and focus there instead of top of the screen

Hi,

New to Ionic. I am currently making a chat room app with Ionic and Firebase. One UX feature I have no idea how to create - So all the text message app will show the latest message at the bottom of the screen when loaded. And you scroll back up to see the pervious conversation…Firebase default load the newest message at the bottom which is great. But when ionic load the view, it does not scroll all the way to the bottom. (it default all the way at the top showing the oldest message). How can I change this behavior in ionic - make the view start at the bottom of the screen?

Also, any good example code I can find that implement infinite scroll (upward)? So when user scroll to the top of the page (defined in Firebase - only load 10 message in 1 page), it trigger firebase to load the next page (like in Apple Text Message App?)

it would be helpful if you added some of your code for us to look at to see what the specific issue is you are having?

You can use $ionicScrollDelegate.scrollBottom(true); to scroll to the bottom. Implementing infinite scroll at the top of the list is a lot more work. You can however check out ionic’s pull-to-refresh which is implemented at the top of a list. It’s different from infinite scroll but in your case might be what you are looking for.

1 Like

$ionicScrollDelegate.scrollBottom(true); is what I am looking for. But unfortunately, it only fire when I put it inside a ng-click function. When initial load the controller, it seems like does not fire and no scroll action happen. If I try to set delegate-handle=“mainScroll” onto my div as the doc said, it throw a warning: " Delegate for handle “mainScroll” could not find a corresponding element with delegate-handle=“mainScroll”! scrollBottom() was not called!
Possible cause: If you are calling scrollBottom() immediately, and your element with delegate-handle=“mainScroll” is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to scrollBottom() and try again."

I use the $timeout like that to surround the call like:

$timeout(function(){
        $ionicScrollDelegate.$getByHandle('mainScroll').scrollBottom(true);
    }, 5000);

It stills do nothing and throw the same error.

So here is my code:

angular.module('cApp').controller('roomCtrl', ['$rootScope', '$scope', '$firebase', 'MyFirebaseService', '$stateParams', '$state', '$ionicScrollDelegate', '$timeout', roomCtrl]);

function roomCtrl($rootScope, $scope, $firebase, MyFirebaseService, $stateParams, $state, $ionicScrollDelegate, $timeout) {
    
    var roomId = $stateParams.id

    $ionicScrollDelegate.scrollBottom(true);
     
    MyFirebaseService.checkSession();
    $scope.noData = false;
    $scope.currentUser = null;
    $scope.currentText = null;
    $scope.messages = [];
    
    var roomRef = new Firebase($rootScope.baseUrl + "chatrooms/" + roomId); 
    var messagesRef = roomRef.child('messages');

    messagesRef.on('child_added', function(snapshot){
        var snapshotVal = snapshot.val();
        var timeDisplay = moment(snapshot.val().postTime).fromNow();
        $scope.messages.push({
            user:snapshotVal.user,
            text:snapshotVal.text,
            timeDisplay: timeDisplay
        });
        console.log (snapshotVal);
        MyFirebaseService.hide();
        $ionicScrollDelegate.$getByHandle('mainScroll').scrollBottom(true);
    });

    var userAccountRef = new Firebase($rootScope.baseUrl + "users/" + $rootScope.userId); 
    userAccountRef.on("value", function(snapshot){
        var data = snapshot.val();
        $scope.currentUser = data.name;
        $scope.profileImgUrl = data.profilepic;
        $scope.postTime = Date.now();
        console.log ($scope.postTime);

        $scope.sendMessage = function() {
            var newMessage = {
                user: $scope.currentUser,
                text: $scope.currentText,
                postTime: $scope.postTime
            };

            messagesRef.push(newMessage);
            $scope.currentText = null;
        };
    });
};

When refresh the browser on this page or send message onto Firebase (which call the on function) will fire the scroll to bottom. But initial load (like redirect from other page, go from other page to this page via a menu system) will not fire the scrolling (as you see in my code I called it twices)

Ops…the $timeout function does work. So i did this

$timeout(function(){
        $ionicScrollDelegate.scrollBottom(true);
    });

And it work in initial load as well…why? I don’t really get the timeout function to make thing load…

Ive read somewhere that putting things in a $timeout() places them last in the hierarchy of objects to be updated during an $apply sequence. Perhapse it was a timing issue in your app, and wrapping it in a $timeout has meant that the code executes at the correct time?

I know that I have managed to fix some issues with my apps having stuttery screen refreshes or missed refreshes by putting some of the refresh code in a $timeout().

Okay. I just deploy on my iPhone and it still create some display error with this method.

So I put

$timeout(function(){
    $ionicScrollDelegate.scrollBottom(true);
});

inside

messagesRef.on('child_added', function(snapshot)

As you see in my above code. So each time child_added, ionicScrollDelegate will be called. So both initial page load and add new comment scroll the view. It works nicely in Chrome and in iOS simulators. But when I deploy the app on my iPhone, the whole view jump up like 100 px (maybe about the height of the navigation bar). Please look at the picture:

iOS simulator:

iPhone running iOS 8.1.3

How can I get the app in iPhone not jump up but display as the iOS simulator screen shot?

1 Like

Delegate for handle “mainScroll” could not find a corresponding element with delegate-handle=“mainScroll”! scrollBottom() was not called!
Possible cause: If you are calling scrollBottom() immediately, and your element with delegate-handle=“mainScroll” is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to scrollBottom() and try again.

I getting this warning

Yes me too! I don’t know what is wrong. But if you do not use delegate-handle (multiple scroll) on the view, this error will not show up. I wrap a timeout as suggested and it is still throw out the error. But again, anyone experience my problem of the “jumping up” in iOs when using $ionicScrollDelegate.scrollBottom(true) in the initial view load?