OnsenUI | Working With Infinite Scroll

Written by on April 9, 2015

OnsenUI | Working With Infinite Scroll

With the advent of mobile devices, an infinite scroll functionality became a very popular feature. This feature is similar in nature to pull-to-refresh though, in this case, as the user scrolls, an application is loading additional content to the bottom of a list. Data is fetched in batches as needed, pulling a fixed number of records at a time.

The OnsenUI can do this but for some reason this functionality is not even described in the official documentation. To achieve this OnsenUI provides ons-scroller directive which makes the inner content scrollable.

This article will cover everything you need to know about this feature, you will also find a working example.

This statement may sound silly, but this is a highly important feature. Without it, as number of list elements rises, our application would gradually become slower and slower. Hybrid mobile applications just can’t handle large number of list items; I managed to witness that while I was working with jQuery Mobile. Nothing changed since that time; even modern mobile frameworks can’t compete with native application scrolling.

Note: If this tutorial was helpful, you need further clarification, something is not working or you have a request for another Ionic post? Furthermore, leave me a comment below if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com. Thanks and have a nice day!

Table of Contents

[spoiler title=” Click here if you want to see other tutorials, this is the 11th tutorial out of 12 total.”]

[/spoiler]

Intro

<ons-scroller 
    infinit-scroll-enable="canWeLoadMoreContent()" 
    can-load="true" 
    on-scrolled="populateList()" 
    threshold="20" 
    style="height:100%">
</ons-scroller>

The ons-scroller directive allows you to scroll inner content. Currently, it’s only usable on mobile devices.

The expression you pass in for on-scrolled is called when the user scrolls greater than distance set in a threshold attribute.

The expression you pass for infinit-scroll-enable requires true/false to determine if infinite scrolling is enabled or disabled.

Example

This example will use a Faker.js framework. For those of you who never heard of this framework, it’s used for data faking. I reviewed it (plus few more frameworks) in one of my earlier articles; find it here.

A short walk through, when this example first initializes it will generate ten list elements; every call to on-infinite function will produce ten additional list items (each time you scroll to the bottom).

Demo

Embedded working example

Ionic Framework Infinite Scroll Example

Warning: Native looking scrolling is not supported in desktop browsers so you will need to use your mouse scroll wheel.

HTML:

<html>

<head>
  <script src="https://code.angularjs.org/1.3.0/angular.js"></script>
  <script src="http://onsenui.io/OnsenUI/build/js/onsenui.js"></script>
  <script src="http://marak.com/faker.js/js/faker.js"></script>
  <script src="script.js"></script>
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsenui.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsen-css-components.css" />
  <link rel="stylesheet" href="style.css" />
</head>

<body ng-controller="ListCtrl">

  <ons-navigator animation="slide" var="app.navi">
    <ons-page>
      <ons-toolbar class="toolbar-black">
        <div class="center">OnsenUI Infinite Scroll Example</div>
      </ons-toolbar>

      <ons-scroller infinit-scroll-enable="canWeLoadMoreContent()" can-load="true" on-scrolled="populateList()" threshold="20" style="height:100%">

          <ons-list-item class="list-item-container" ng-repeat="list in _list">
            <ons-row style="padding: 10px 10px 5px 0;">
              <ons-col width="145px">
                <img ng-src="{{list.image}}" class="thumbnail">
              </ons-col>
              <ons-col>
                <div style="height: 30px;">
                  <h4>{{list.name}}</h4>
                </div>
                <div style="height: 30px; font-size: 13px;">
                  <i class="fa fa-map-marker"></i> {{list.address}}
                </div>
                <div style="height: 30px; font-size: 13px;">
                  <i class="fa fa-phone"></i> {{list.phone}}
                </div>
              </ons-col>
              <ons-col width="40px"></ons-col>
            </ons-row>
          </ons-list-item>

          <ons-list-item ng-show="isLoading">
            <div class="loader-container">
              <ons-icon icon="spinner" size="40px" spin="true"></ons-icon>
            </div>
          </ons-list-item>

      </ons-scroller>

    </ons-page>
  </ons-navigator>


</body>

</html>

JavaScript:

var module = ons.bootstrap('my-app', ['onsen']);

module.controller('ListCtrl', function($scope, $timeout) {
  
  $scope._list = [];  
  $scope.isLoading = false;

  $scope.populateList = function() {
    
    if($scope.isLoading) return;
  
     $timeout(function(){
        for (var i = 0; i <= 9; i++) {
          
          var firstName = faker.name.firstName();
          var lastName = faker.name.lastName();      
          
          $scope._list.push({ name: firstName + " " + lastName, 
                              address: faker.address.streetAddress(),
                              phone: faker.phone.phoneNumber(),
                              image: faker.internet.avatar()
          });
        }    
        console.log($scope._list.length);
         $scope.isLoading = false;
     },1000);
  
     $timeout(function() {
       $scope.isLoading = true;  
     });    
  }

  $scope.canWeLoadMoreContent = function() {
    return ($scope._list.length > 49) ? false : true;
  }  

  $scope.populateList();
  
});

Walkthrough

When ListCtrl controller first initializes it will create an empty _list object; we’ll use it to store application list data:

$scope._list = [];  

JavaScript will immediately populate it using a function call:

$scope.populateList(); 

Application is calling this function:

$scope.populateList = function() {
    
    if($scope.isLoading) return;
  
     $timeout(function(){
        for (var i = 0; i <= 9; i++) {
          
          var firstName = faker.name.firstName();
          var lastName = faker.name.lastName();      
          
          $scope._list.push({ name: firstName + " " + lastName, 
                              address: faker.address.streetAddress(),
                              phone: faker.phone.phoneNumber(),
                              image: faker.internet.avatar()
          });
        }    
        console.log($scope._list.length);
         $scope.isLoading = false;
     },1000);
  
     $timeout(function() {
       $scope.isLoading = true;  
     });    
}

Function generates ten list elements per call using Faker.js to autogenerate fake data. $timeout is needed here because without it list directive will not be updated. Look at it as a broadcast that new items are available.

This is applications ons-scroller directive:

<ons-scroller 
    infinit-scroll-enable="canWeLoadMoreContent()" 
    can-load="true" 
    on-scrolled="populateList()" 
    threshold="20" 
    style="height:100%">
</ons-scroller>

Directive is configured to trigger a function populateList() when a distance reach a threshold of 20. This example will show max. 50 elements; it will disable infinite scrolling if number of list elements surpass that number. Disabling/enabling can be achieved using an expression we’re sending through infinit-scroll-enable attribute:

$scope.canWeLoadMoreContent = function() {
    return ($scope._list.length > 49) ? false : true;
}  

Author’s Notes

I need to apologize in advance, but I need to get this off my chest. I’m becoming more and more disappointed with this framework. What used to look as a great documentation now looks less and less promising. For example, I don’t even want to ask what’s the point of ons-scroller directive, other frameworks can do this out od the box. Ons-scroller won’t even work in desktop Chrome environment, ffs, I would like to be able to test this feature without using my smartphone.

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.



Categories

2 thoughts on “OnsenUI | Working With Infinite Scroll”

Leave a Reply