Search code examples
javascriptangularchationic2autoscroll

ionic 2 + angular 2 : auto scroll to bottom of list / page / chat


I'm trying to code a page with two segments "chat" and "content". I want that one "chat" segment the page auto-scroll to the bottom with no effect. The chat is a <ion-list> with several <ion-item>.

<ion-list>
<ion-item> item 1 </ion-item>
<ion-item> item 2 </ion-item>
....
<ion-item> item 20 </ion-item>
<ion-item> item 21 </ion-item> <!-- user should see directly this item on bottom of the page -->
</ion-list>

I'm using Javascript, not typescript, and I don't wan't to use jQuery. Thanks :) Plus, when I go to "content" segment and go back to "chat" I want to auto-scroll again the chat.


Solution

  • First off all, @rinukkusu answer is right but it doesn't work on my case because <ion-content> (parent of <ion-list>) has some bugs with it (ionic developers are working on that), so I had to put that element with scroll:hidden and create a second content inside to apply the auto-scroll. Finally with the right (s)css I called the function on construtor when the page loads and then each time the users clicks on "chat" segment.

    chat.html

    <!-- I create the segment and call the `autoScroll()` when users clicks on "chat" -->
    <ion-toolbar primary class="toolbar-segment">
        <ion-segment light [(ngModel)]="segment">
            <ion-segment-button value="chat" (click)="autoScroll()">
                Chat
            </ion-segment-button>
            <ion-segment-button value="profile">
                Profile
            </ion-segment-button>
        </ion-segment>
    </ion-toolbar>
    
    <!--I wrote the css inline just as example. 
      DON'T do it on your project D: -->
    
    <!-- overflow:hidden prevent the ion-content to scroll -->
    <ion-content [ngSwitch]="segment" style="overflow: hidden;">
    
        <!-- height: 100% to force scroll if the content overflows the container.
             #chat-autoscroll is used by javascript.-->
        <div class="content-scroll" id="chat-autoscroll" *ngSwitchWhen="'chat'" style="height: 100%; overflow: scroll">
            (... make sure the content is bigger 
            than the container to see the auto scroll effect ...)
        </div>
    
        <!-- here it's just a normal scroll  -->
        <div *ngSwitchWhen="'profile'" class="content-scroll" style="height: 100%; overflow: auto">
          (... content of profile segment ...)
        </div>
    
    </ion-content>
    

    chat.js

    constructor () {
    
        // when the user opens the page, it shows the "chat" segment as initial value
        this.segment = 'chat'; 
    
        // when page loads, it calls autoScroll();
        if (this.segment == 'chat') {
            console.log('chat');
            this.autoScroll();
        };
    }
    
    /*Here comes the tricky. 
     If you don't use setTimeout, the console will say that
     #chat-autoscroll doesn't exist in the first call (inside constructor). 
     This happens because the script runs before the DOM is ready. 
     I did a workaround with a timeOut of 10ms.
     It's enough time to DOM loads and then autoScroll() works fine.
    */
    autoScroll() {
        setTimeout(function () {
            var itemList = document.getElementById("chat-autoscroll");
            itemList.scrollTop = itemList.scrollHeight;
        }, 10);
    }
    

    Conclusion: The function is called twice. When the page is loaded (constructor) and each time the user comes back to "chat" segment. (click)="autoScroll()"

    I hope this helps someone. If you know better way, let me know! I started playing with Angular2 and Ionic2 a couple of weeks ago so there is a lot of concepts/bases that I might be missing here.

    Thanks :)