Last Updated: 16 May 2016
Lab Length: 30 minutes
Objective
As your data grows in size you may not want to always pull down all of the data and instead only pull down only a few records at a time. The Back& service that we are using supports paging and the UI component from Ionic for paging to called infinite scroll. Infinite scroll is pretty easily to implement but it does have some quirks that can be baffling to get working correctly if you have not done it before. This lab will guide you through implement infinite scroll and working through the quirks of it.
Key Concepts:
- ionic infinite scroll component
- angular ng-if
- true paging with Back&
Table of Contents
15.0: Paging in Back&
The first thing we need to do is implement paging in the Back& service call for getting projects. This functionality is supported out of the box. We just have to tell Back& which page to start on and how many records to pull.
- Open the www/js/services/projects.service.js file
To the
getProjectsfunction add 2 parameters calledpageNumberandpageSizefunction getProjects(pageNumber, pageSize){ ..... }Now we need to add the
pageNumberandpageSizeparameters to the params objects. The code below sets default values for pageSize and pageNumber if nothing is passed into the function.return $http({ method: 'GET', url: Backand.getApiUrl() + '/1/objects/project', params: { sort: '[{ "fieldName": "name", "order": "asc" }]', pageSize: pageSize || 10, pageNumber: pageNumber || 1 } }).then(function (result) { return result.data.data; });
15.1 Paging in the Project Controller
Now that the Projects service supports paging, we need to update the ProjectsController to support paging.
- Open the www/js/controllers/projects.controller.js
We need to add variables to track the page number and page size. We will also set them to the default values that we want to use which is a page size of 10 and page number set to 0 (we will increment to 1 in the first call).
vm.pageNumber = 0; vm.pageSize = 10;Create a function called
getMoreProjects. This function will get any additional data from the Back& API, check to see if we have more paging of data to get, append the results to the existing data and tell the infinite scroll that it has completed.function getMoreProjects() { vm.pageNumber = vm.pageNumber + 1; ProjectsService.getProjects(vm.pageNumber, vm.pageSize) .then(function (result) { var rowNum = result.data.length ; if (rowNum > 0) { vm.projects = vm.projects.concat(result.data); } }) .finally(function () { $scope.$broadcast('scroll.infiniteScrollComplete') }); }Don’t forget to expose the
getMoreProjectsfunction to the viewvm.getMoreProjects = getMoreProjects;
We are technically done with the implementation of the infinite scroll in the controller. However, one of the quirks that I ran into is that the ion-refresher was causing the infinite scroll to trigger. To stop it from doing this, I added a refreshing flag to the getProjects function that tells the view that we are refreshing so that we can let the infinite scroll know not to trigger right now. The flag is called vm.refreshing set to true on entering the function and in the finally block set to false so that the infinite scroll can be turned back on.
function getProjects() {
vm.refreshing = true;
ProjectsService.getProjects().then(function (response) {
vm.projects = response;
})
.finally(function () {
$scope.$broadcast('scroll.refreshComplete');
vm.refreshing = false;
});
}
We need to modify the
getProjectscall to the ProjectsService to pass in the pageNumber of 1 and pageSize. Since thegetProjectsis used for both getting initial data as well as refreshing data, we need to do a little bit of math to determine how many records to pull in since the infinite scroll could have pull in more than 1 page of data. The formula for records to pull ispageSize * pageNumberfunction getProjects() { vm.refreshing = true; ProjectsService.getProjects(1, vm.pageSize*vm.pageNumber).then(function (response) { vm.projects = response; }) .finally(function () { $scope.$broadcast('scroll.refreshComplete'); vm.refreshing = false; }); }The infinite scroll will initially be called so we do not need to call the
getProjectsin theactivatefunction but need to initialize thevm.projectsarray at the top of theProjectsControllerfunctionfunction ProjectsController(ProjectsService, $ionicModal, $scope, $state, $ionicPopup, $ionicListDelegate) { var vm = this; ...... vm.projects = []; activate(); ...... }The last thing we need to do in the controller is to check if we have more data to load by seeing if the
totalRowsproperty on the data results is less than the total number of possible records for the page number and page size that we are on. Since we need to check this in thegetProjectsandgetMoreProjectsfunction, we will want to create a function to hold this logic and call it from those methods.function setMoreDataCanBeLoaded(resultData) { if (resultData.totalRows < vm.pageSize * vm.pageNumber) { vm.moreDataCanBeLoaded = false; } else { vm.moreDataCanBeLoaded = true; } }Don’t forget to expose the
vm.moreDataCanBeLoadedflag to the viewvm.moreDataCanBeLoaded = true;The function
setMoreDataCanBeLoadeddoes not however need to be exposed to the view since it is only called within the controller functions and not invoked from the UINow you need to add the call to
setMoreDataCanBeLoadedin thegetProjectsandgetMoreProjectsfunctionsfunction getProjects() { .... ProjectsService.getProjects(1, vm.pageSize * vm.pageNumber).then(function (response) { .... setMoreDataCanBeLoaded(response); }) ..... } function getMoreProjects() { ...... ProjectsService.getProjects(vm.pageNumber, vm.pageSize) .then(function (result) { setMoreDataCanBeLoaded(result); var rowNum = result.data.length; if (rowNum > 0) { vm.projects = vm.projects.concat(result.data); } ..... }
15.2 Paging in the View
We are now ready to add the ion-infinite-scroll to the view and test out the paging functionality.
- Open the www/templates/projects.html
- After the
ion-list, use thei1_infinitescrollsnippet to get the<ion-infinite-scroll>- on-infinite: vm.getMoreProjects()
- distance: 1%
By default the infinite scroll will immediately check if there is more data which means that we no longer need to call
getProjectsin theactivatefunction.<ion-infinite-scroll on-infinite="vm.getMoreProjects()" distance="1%" > </ion-infinite-scroll>The last thing we need to implement is the check on the
ion-infinite-scrollto see if more data can be loaded and that the refresher is not running. To do this we are going to use an Angular ng-if statement on theion-infinite-scroll.<ion-infinite-scroll on-infinite="vm.getMoreProjects()" distance="1%" ng-if="vm.moreDataCanBeLoaded && !vm.refreshing" > </ion-infinite-scroll>- If you don’t already have ionic serve running, open a command prompt and run the command ionic serve
- In your web browser, open http://localhost:8100. As long as you have enough projects listed, once you get near the bottom of the viewable list of projects, it will trigger the infinite scroll to pull in more projects.
Wrap-up
Thank goodness we did not have to implement all of the logic to create our own infinite scroll component. Using the Ionic infinite scroll is a breeze to implement and get working correctly. The biggest thing to remember when using the infinite scroll component is to set the flag to only allow it to run when it thinks there is more data else you can get into an infinite loop of checking for updates if the user is anywhere near the bottom of the page.
You would also want to implement an infinite scroll on the task page or increase the page size to some amount that is far greater than would ever expect a single project to have input.