Infinite Scroll in Ionic Framework Pulling Real Data By Month

By: Ryan Wong at

Here’s my tutorial for creating an infinite scroll querying by month and year.

Basically, we have a header bar above ion-content where it displays the month and year.

If user clicks the prev button, it requery the server with the correct month and year.

If user clicks the next button, it requery the server with the correct month and year.

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div class="calendar-switch">
<div class="left-calendar" ng-click="prev()"><</div>
<div class="calendar-month"> {{date | date:'MMMM'}} {{date | date:'y'}}</div>
<div class="right-calendar" ng-click="next()">></div>
</div>
<ion-content class="has-calendarheaders">
<ion-refresher
pulling-text="Pull to refresh..."
on-refresh="doRefresh()">
</ion-refresher>
<ul class="calendar-listing">
<li ng-repeat="oneItem in items">
<a class="calendar-row" href="#calendarView/{{oneItem.id}}">
<div class="calendar-detail">
{{oneItem.name}}<br/>
{{oneItem.location}}<br/>
{{oneItem.postalCode}}<br/>
{{oneItem.startTime}} to {{oneItem.endTime}}
</div>
</a>
</li>
</ul>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="10%">
</ion-infinite-scroll>
<div class="noSourceFound" ng-if="noItemFound">
<p>Sorry No Event Found</p>
</div>
</ion-content>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.has-calendarheaders{
top: 186px;
}
.calendar-switch{
height: 50px;
text-align: center;
top: 138px;
position: fixed;
width: 100%;
z-index: 4;
padding: 10px 0;
.left-calendar {
float:left;
width:10%;
font-weight: bold;
}
.calendar-month {
float:left;
width: 80%;
}
.right-calendar {
float: right;
width: 10%;
font-weight: bold;
}
}

JS Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
function CalendarLatestCtrl($s, cS) {
$s.items = [];
$s.date = new Date();
$s.page = 1;
$s.noMoreItemsAvailable = false;
$s.noItemFound = false;
$s.next = function(){
$s.date.setMonth($s.date.getMonth() + 1);
$s.items = [];
$s.page = 1;
$s.noItemFound = false;
$s.noMoreItemsAvailable = false;
}
$s.prev = function(){
$s.date.setMonth($s.date.getMonth() - 1);
$s.items = [];
$s.page = 1;
$s.noItemFound = false;
$s.noMoreItemsAvailable = false;
}
$s.loadMore = function(){
cS.getCalendarAll($s.page, $s.date.getMonth() + 1, $s.date.getFullYear()).then(function(items) {
if (items.numPages == items.page){
$s.noMoreItemsAvailable = true;
$s.$broadcast('scroll.infiniteScrollComplete');
}
if (items.numPages == 0 || items.total == 0){
$s.noMoreItemsAvailable = true;
$s.noItemFound = true;
}
items.list = items.list.map(function(oneEvent){
oneEvent.dateObject = new Date(oneEvent.date);
return oneEvent;
});
$s.page++;
$s.items = $s.items.concat(items.list);
$s.$broadcast('scroll.infiniteScrollComplete');
});
};

$s.doRefresh = function(){
$s.items = [];
$s.page = 1;
$s.noMoreItemsAvailable = false;
$s.loadMore();
$s.$broadcast('scroll.refreshComplete');
};
}
angular.module('controller', [])
.controller('CalendarLatestCtrl', ['$scope', 'calendarService', CalendarLatestCtrl]);

AJAX Request

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"page" : 1,
"numPages": 7,
"total": 10,
"list" : [{
"id" : 1,
"date" : "2015-05-02 12:34:32",
"blah": "blah"
},{
"id" : 1,
"date" : "2015-05-01 12:34:32",
"blah": "blah"
}]
}

Angular Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function calendarService(baseUrl, $q, $http){
this.someUrl = baseUrl() + '/api/v1/someurl';

this.getCalendarAll = function(page, month, year){
var deferred = $q.defer();
$http({
method: 'GET',
url: someUrl + '?page=' + page + '&month=' + month + '&year=' + year
})
.success(function(data) {
return deferred.resolve(data);
})
.error(function(err,status) {
return deferred.reject(err);
});
return deferred.promise;
}};

angular.module('services', [])
.service('calendarService', ['baseUrl', '$q', '$http', calendarService])