The Official Ionic Blog

Build amazing native and progressive web apps with HTML5

This is a guest post by Andrew McGivery, an application developer with a strong background in
Android, AngularJS, Ionic, C#, SQL, and front end development. Andrew writes often about Ionic and how to build great
hybrid apps. Read more on Andrew’s personal blog

With the rise of social networks, the “feed” has become a popular design pattern, especially in mobile apps. The idea is to load in new items to the top of a feed by pulling down from the top of the list until you see a loading indicator, letting go, and watching as new items magically (not really) add themselves in.

Ionic has an awesome directive that has undergone a redo fairly recently to accomplish exactly this. In this post, we’ll break down a basic example of using this directive, a list, and the Random User API to see how to use the directive with example data (feel free to follow along on CodePen).

ionRefresher (Pull to Refresh Directive)

The Ionic directive we are going to use is the ion-refresher (Official Documentation). The most basic usage is as follows:

<ion-refresher on-refresh="doRefresh()"></ion-refresher>

on-refresh should point to a $scope function that gets the new data, updates a list, and then lets the refresher know it is done. This refresher should be above some kind of list.

View

For our example, we’ll be using the following view markup:

<ion-refresher on-refresh="doRefresh()"></ion-refresher>
<ion-list>
  <ion-item class="item-avatar" ng-repeat="item in items">
    <img src="{{item.user.picture.thumbnail}} " />
    ## {{item.user.name.first}} {{item.user.name.last}}
    <p>{{item.user.location.city}} {{item.user.password}}</p>
  </ion-item>
</ion-list>

which looks something like this, once rendered:

rendered list

Remember that this list iterates over the $scope.items array.

ng-repeat="item in items"

Factory

In our example, we’re going to be making a call to the Random User API to get some data to play with. To do this, we’ll create a factory that makes these API calls. This factory will have two methods: GetFeed and GetNewUser. GetFeed will be called when our app loads to get the initial data, and the GetNewUser will be called each time we do a pull to refresh.

.factory('PersonService', function($http){
  var BASE_URL = "http://api.randomuser.me/";
  var items = [];

  return {
    GetFeed: function(){
      return $http.get(BASE_URL+'?results=10').then(function(response){
        items = response.data.results;
        return items;
      });
    },
    GetNewUser: function(){
      return $http.get(BASE_URL).then(function(response){
        items = response.data.results;
        return items;
      });
    }
  }
})

Our GetFeed call returns 10 results, and each call to GetNewUser returns 1 result.

Controller

Our controller needs to do 2 things:

  1. Fill the feed with the initial items
  2. Handle the pull to refresh

First, to fill our feed, we’ll want to make a call to the PersonService and assign the result to the $scope.items array:

.controller('MyCtrl', function($scope, $timeout, PersonService) {
  $scope.items = [];

  PersonService.GetFeed().then(function(items){
    $scope.items = items;
  });
});

Next, we need to handle the pull to refresh. Recall we configured our directive to call a doRefresh function. We’ll need to define this function:

$scope.doRefresh = function() {

}

In this function, we should call the GetNewUser function and add these items to the beginning of the array.

$scope.doRefresh = function() {
  PersonService.GetNewUser().then(function(items){
    $scope.items = items.concat($scope.items);
  });
};

You’ll notice we are using the array.concat function to add the items in. This is because items is an array, so we need to add the two arrays together.

We still need to do one final thing. We need to let the scroller know that we’re done loading in the new items, so it can hide the loading indicator. To do this, we need to broadcast the scroll.refreshComplete event.

$scope.doRefresh = function() {
  PersonService.GetNewUser().then(function(items){
    $scope.items = items.concat($scope.items);

    //Stop the ion-refresher from spinning
    $scope.$broadcast('scroll.refreshComplete');
  });
};

In its entirety, our controller looks like this:

.controller('MyCtrl', function($scope, $timeout, PersonService) {
  $scope.items = [];

  PersonService.GetFeed().then(function(items){
    $scope.items = items;
  });

  $scope.doRefresh = function() {
    PersonService.GetNewUser().then(function(items){
      $scope.items = items.concat($scope.items);

      //Stop the ion-refresher from spinning
      $scope.$broadcast('scroll.refreshComplete');
    });
  };

});

Conclusion

Using the code above (full code on CodePen), you can accomplish this common pull to refresh patten in your Ionic Apps. Questions? Feel free to comment below!

  • Nico Hernandez Torres

    Hi, There is a way to refresh the list down?

    • Ramadhevi Rk

      append items to the end of $scope.items!!!

      $scope.doRefresh = function() {
      PersonService.GetNewUser().then(function(items){
      $scope.items = items.concat($scope.items);

      //Stop the ion-refresher from spinning
      $scope.$broadcast(‘scroll.refreshComplete’);
      });
      };

      just do as

      $scope.doRefresh = function() {
      PersonService.GetNewUser().then(function(items){
      $scope.items = $scope.items.concat(items);

      //Stop the ion-refresher from spinning
      $scope.$broadcast(‘scroll.refreshComplete’);
      });
      };

      • Lauro Rafael

        How do I update only new records?
        So it is replicating all the json records.
        Help… tnks

  • Ramadhevi Rk

    hello Andrew!!
    I have been following your articles for a while.. Which are elegant and useful.. keep delivering the articles!

    I need some suggestions on this!
    I have requested initially 10 products from my rest api service. How to request for next 10 products when ion-refresher gets called? i need to repeat it for displaying 100 products by Requesting 10 products each time..

    • Sergey Shvaitser

      just use collection-repeat instead ng-repeat

  • The Down Country

    I get a concat error when I try the code.

  • Shivam01

    Hi Andrew,
    I am stuck on some cases , suppose I deleted some or single item of list from web application , then come over mobile app (iOS) , what i see that the duplicate list of items will appear at bottom for 3 seconds and then move to the left side, then entire list will properly appear , is that way of pulling data from web services when deleted from web.

    And over the device delete task in ios device working fine , as I am doing swipe left and button of delete bla bla bla.

    So why its UI not supporting above I mentioned case.

    Regards
    Shivam

  • http://cauealmeida.com Cauê Almeida

    Great. Is it possible to broadcast the scroll.refreshComplete from a service?

  • Rako Nda ᵀᴴᴱ ᴼᴿᴵᴳᴵᴻᴬᴸ

    what if we want to add the new data in head of array ?

  • Filbert Sugianto Manunggal

    Hi andrew,

    My name is filbert. I have been trying to use ionic refresher. it completely work well in web (using ionic serve). But when I build apk and I am trying in my phone. I can’t drag down the refresher. do you know why?

  • Lauro Rafael

    How do I update only new records?
    So it is replicating all the json records. Tnks