HI WELCOME TO KANSIRIS

Ionic and Angular: Infinite Scrolling with RESTful APIs

We have seen series of posts on developing a mobile application using Ionic and AngularJS. One of my previous articles which deal with insertion and deletion of posts using RESTful API. Similarly, today’s post makes use of RESTful API. These days, a single page web applications are most commonly used ones, because of which there is a need to show loads of data on the same page as we keep on scrolling. This infinite scrolling avoids pagination system.

Infinite Scrolling using Ionic and Angular with RESTful APIs


Live Demo 



Database Design
To build the user social login system, you have to create a user table.

Users
User table contains all the users social details.
CREATE TABLE users(
user_id int AUTO_INCREMENT PRIMARY KEY,
email varchar(300),
name varchar(200),
provider varchar(50),
provider_id varchar(200),
provider_pic varchar(200),
token varchar(500));

Feed
This table contains user daily updates.
CREATE TABLE feed(
feed_id int PRIMARY KEY AUTO_INCREMENT,
feed text,
user_id_fk int,
created int
);


home.html
Go to your angular project and include ion-infinite-scroll tag with doInfinite function. This HTML tag will trigger doInfinite function when you reach page scroll down.
<ion-content padding>
<h2>Welcome to {{userDetails.name}}</h2>
 <ion-item id="udpateBox">
      <textarea #updatebox [(ngModel)]="userPostData.feed" autofocus></textarea>
    <ion-row>
       <button ion-button color="energy"(click)="feedUpdate()">Update</button>
    </ion-row>
</ion-item>

<ion-card *ngFor="let item of dataSet; let msgIndex = index">
 <ion-item>
    <ion-icon name="trash" item-right (click)="feedDelete(item.feed_id, msgIndex)"></ion-icon>
    <ion-card-content>
    <p [innerHTML]="item.feed | linky"></p>
    <span>{{this.converTime(item.created) | amTimeAgo}}</span>
    </ion-card-content>
</ion-item>
</ion-card>

<ion-infinite-scroll (ionInfinite)="$event.waitFor(doInfinite())">
   <ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>

home.ts.
In getFeed() function we need to set the last created timestamp for new scroll data. Explained more on video tutorial
import { Component } from "@angular/core";
import { NavControllerAppAlertController } from "ionic-angular";
import { AuthService } from "../../providers/auth-service";
import { Common } from "../../providers/common";

@Component({ selector: "page-home", templateUrl: "home.html" })
export class HomePage {
      public userDetails: any;
      public resposeData: any;
      public dataSet: any;
   
     userPostData = {
        user_id: "",
        token: "",
        feed: "",
        feed_id: "",
        lastCreated: ""
     };

constructor(
   public common: Common,
   private alertCtrl: AlertController,
   public navCtrl: NavController,
   public app: App,
   public authService: AuthService) {
const data = JSON.parse(localStorage.getItem("userData"));
   this.userDetails = data.userData;
   this.userPostData.user_id = this.userDetails.user_id;
   this.userPostData.token = this.userDetails.token;
   this.userPostData.lastCreated = "";
   this.getFeed();
}

getFeed() {
  this.common.presentLoading();
  this.authService.postData(this.userPostData"feed").then(
  result => {
     this.resposeData = result;
     if (this.resposeData.feedData) {
        this.common.closeLoading();
        this.dataSet = this.resposeData.feedData;
        // Data set length
        const dataLength = this.resposeData.feedData.length;
        this.userPostData.lastCreated = this.resposeData.feedData[dataLength- 1].created;
      } else {
       console.log("No data");
     }
},
err => {
   //Connection failed message
}
);
}

feedUpdate() {
// API update feed
}

feedDelete(feed_id, msgIndex) {
// API delete feed
}

doInfinite(e): Promise<any> {
console.log("Begin async operation");
   return new Promise(resolve => {
      setTimeout(() => {
         // API Connection for more updates
         resolve();
       }, 500);
      });
}

converTime(time) {
   let a = new Date(time * 1000);
   return a;
}

backToWelcome() {
   const root = this.app.getRootNav();
   root.popToRoot();
}

logout() {
//Api Token Logout
   localStorage.clear();
   setTimeout(() => this.backToWelcome(), 1000);
}
}


Download PHP Restul Project
$git clone https://github.com/srinivastamada/PHP-Slim-Restful.git


PHP RESTful API index.php
Improved feed() function with limited user feed results. If lastCreated is present, we need to get the data based on last timestamp.
<?php
require 'config.php';
require 'Slim/Slim.php';


\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();


$app->post('/login','login'); /* User login */
$app->post('/signup','signup'); /* User Signup */
$app->post('/feed','feed'); /* User Feeds */
$app->post('/feedUpdate','feedUpdate'); /* User Feeds */
$app->post('/feedDelete','feedDelete'); /* User Feeds */
//$app->post('/userDetails','userDetails'); /* User Details */


$app->run();


/************************* USER LOGIN *************************************/
/* ### User login ### */
function login() {
// ....
}


/* ### User registration ### */
function signup() {
// ....
}



/* ### internal Username Details ### */
function internalUserDetails($input) {
// ....
}


function feed(){
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$user_id=$data->user_id;
$token=$data->token;
$lastCreated = $data->lastCreated;
$systemToken=apiToken($user_id);
try {
     if($systemToken == $token){
       $feedData = '';
       $db = getDB();
     if($lastCreated){
         $sql = "SELECT * FROM feed WHERE user_id_fk=:user_id AND created <:lastCreated ORDER BY feed_id DESC LIMIT 5";
        $stmt = $db->prepare($sql);
        $stmt->bindParam("user_id"$user_idPDO::PARAM_INT);
        $stmt->bindParam("lastCreated"$lastCreatedPDO::PARAM_STR);
}
else{
       $sql = "SELECT * FROM feed WHERE user_id_fk=:user_id ORDER BY feed_id DESC LIMIT 5";
       $stmt = $db->prepare($sql);
       $stmt->bindParam("user_id"$user_idPDO::PARAM_INT);
}
$stmt->execute();
$feedData = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
if{
     echo '{"feedData": ' . json_encode($feedData. '}';
}
else{
    echo '{"feedData": ""}';
}
else{
echo '{"error":{"text":"No access"}}';
}
catch(PDOException $e) {
     echo '{"error":{"text":'. $e->getMessage() .'}}';
}


}


function feedUpdate(){
// ...
}


function feedDelete(){
// ...
}
?>


home.ts
Here doInfinite function makes an API call with lastCreated. If the feed response with empty data, it sets the noRecords values as true.
import { Component } from "@angular/core";
import { NavControllerAppAlertController } from "ionic-angular";
import { AuthService } from "../../providers/auth-service";
import { Common } from "../../providers/common";

@Component({ selector: "page-home", templateUrl: "home.html" })
export class HomePage {
     public userDetails: any;
     public resposeData: any;
     public dataSet: any;
     public noRecords: boolean;
     userPostData = {
        user_id: "",
        token: "",
        feed: "",
        feed_id: "",
        lastCreated: ""
     };

constructor(
public common: Common,
private alertCtrl: AlertController,
public navCtrl: NavController,
public app: App,
public authService: AuthService) {
     const data = JSON.parse(localStorage.getItem("userData"));
     this.userDetails = data.userData;
     this.userPostData.user_id = this.userDetails.user_id;
     this.userPostData.token = this.userDetails.token;
     this.userPostData.lastCreated = "";
     this.noRecords = false
     this.getFeed();
}

getFeed() {
//...
}

feedUpdate() {
//...
}

feedDelete(feed_id, msgIndex) {
//...
}
doInfinite(e): Promise<any> {
console.log("Begin async operation");
   return new Promise(resolve => {
   setTimeout(() => {
      this.authService.postData(this.userPostData"feed").then(
      result => {
         this.resposeData = result;
         if (this.resposeData.feedData.length) {
            const newData = this.resposeData.feedData;
            this.userPostData.lastCreated =this.resposeData.feedData[newData.length - 1].created;

     for (let i = 0i < newData.length; i++) {
        this.dataSet.push(newData[i]);
     }
else {
    this.noRecords = true;
     console.log("No user updates");
}
},
err => {
//Connection failed message
}
);
resolve();
}, 500);
});
}

converTime(time) {
let a = new Date(time * 1000);
return a;
}

backToWelcome() {
//...
}

logout() {
//...
}
}

home.html
Now controlling HTML tag with noRecords values. No records block presents when the noRecords values is true and it stops infinte scrolling action.
<ion-card *ngFor="let item of dataSet; let msgIndex = index">
<ion-item>
   <ion-icon name="trash" item-right (click)="feedDelete(item.feed_id, msgIndex)"></ion-icon>
<ion-card-content>
   <p [innerHTML]="item.feed | linky"></p>
   <span>{{this.converTime(item.created) | amTimeAgo}}</span>
</ion-card-content>
</ion-item>
</ion-card>

<ion-card *ngIf="noRecords">
 <ion-item>
   No Records
  </ion-item>
</ion-card>

<ion-infinite-scroll (ionInfinite)="$event.waitFor(doInfinite())"*ngIf="!noRecords">
   <ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>