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:
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:
- Fill the feed with the initial items
- 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!
13 Comments
Hi, There is a way to refresh the list down?
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’);
});
};
How do I update only new records?
So it is replicating all the json records.
Help… tnks
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..
just use collection-repeat instead ng-repeat
I get a concat error when I try the code.
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
Great. Is it possible to broadcast the scroll.refreshComplete from a service?
what if we want to add the new data in head of array ?
you can use array.unshift(item)
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?
How do I update only new records?
So it is replicating all the json records. Tnks
This does not work, i’m trying to use the refresher in my ionic app to send data via API but the
refresher method gets fired more than once even when i call scroll.refreshComplete event, really weird, an ionic issue i suppose.
2 Trackbacks