This is the continued series of article on developing a mobile app with Ionic and Angular JS. This post deals with updating and deleting any post on the application. This also explains how to show the loading image by making an Ajax call. While deleting a post, it will show an alert message to confirm whether to delete or not. This post is all about this. Hope you all make use of this series of articles on Ionic and Angular to build your own mobile app.
Live Demo
Part 1
Ionic 3 and Angular 4: Create a Welcome Page with Login and Logout.
Video Tutorial
Ionic 3 and Angular 4: PHP Token Based Restful API User Feed Update and Delete.
Database Design
To build the user feed system, you have to create two tables such as Users and Feed. You can check my previous tutorials for creating token-based API system.
Users
User table contains all the users registration details.
CREATE TABLE users(
user_id int AUTO_INCREMENT PRIMARY KEY,
username varchar(50),
password varchar(300),
name varchar(200),
email varchar(300));
user_id int AUTO_INCREMENT PRIMARY KEY,
username varchar(50),
password varchar(300),
name varchar(200),
email varchar(300));
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
);
feed_id int PRIMARY KEY AUTO_INCREMENT,
feed text,
user_id_fk int,
created int
);
Download PHP Restul Project
$git clone https://github.com/srinivastamada/PHP-Slim-Restful.git
PHP RestFul Code
Simple PHP code with Slim framework, included new functions feedUpdate and feedDelete for user insert and delete operations.
<?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 Feed Update */
$app->post('/feedDelete','feedDelete'); /* User Feed Delete */
$app->run();
// Other Functions
function feedUpdate(){
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$user_id=$data->user_id;
$token=$data->token;
$feed=$data->feed;
$systemToken=apiToken($user_id);
try {
if($systemToken == $token){
$feedData = '';
$db = getDB();
$sql = "INSERT INTO feed ( feed, created, user_id_fk) VALUES
(:feed,:created,:user_id)";
$stmt = $db->prepare($sql);
$stmt->bindParam("feed", $feed, PDO::PARAM_STR);
$stmt->bindParam("user_id", $user_id, PDO::PARAM_INT);
$created = time();
$stmt->bindParam("created", $created, PDO::PARAM_INT);
$stmt->execute();
$sql1 = "SELECT * FROM feed WHERE user_id_fk=:user_id ORDER BY
feed_id DESC LIMIT 1";
$stmt1 = $db->prepare($sql1);
$stmt1->bindParam("user_id", $user_id, PDO::PARAM_INT);
$stmt1->execute();
$feedData = $stmt1->fetch(PDO::FETCH_OBJ);
$db = null;
echo '{"feedData": ' . json_encode($feedData) . '}';
} else{
echo '{"error":{"text":"No access"}}';
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
function feedDelete(){
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$user_id=$data->user_id;
$token=$data->token;
$feed_id=$data->feed_id;
$systemToken=apiToken($user_id);
try {
if($systemToken == $token){
$feedData = '';
$db = getDB();
$sql = "DELETE FROM feed WHERE user_id_fk=:user_id AND
feed_id=:feed_id";
$stmt = $db->prepare($sql);
$stmt->bindParam("user_id", $user_id, PDO::PARAM_INT);
$stmt->bindParam("feed_id", $feed_id, PDO::PARAM_INT);
$stmt->execute();
$db = null;
echo '{"success":{"text":"Feed deleted"}}';
} else{
echo '{"error":{"text":"No access"}}';
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
?>
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 Feed Update */
$app->post('/feedDelete','feedDelete'); /* User Feed Delete */
$app->run();
// Other Functions
function feedUpdate(){
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$user_id=$data->user_id;
$token=$data->token;
$feed=$data->feed;
$systemToken=apiToken($user_id);
try {
if($systemToken == $token){
$feedData = '';
$db = getDB();
$sql = "INSERT INTO feed ( feed, created, user_id_fk) VALUES
(:feed,:created,:user_id)";
$stmt = $db->prepare($sql);
$stmt->bindParam("feed", $feed, PDO::PARAM_STR);
$stmt->bindParam("user_id", $user_id, PDO::PARAM_INT);
$created = time();
$stmt->bindParam("created", $created, PDO::PARAM_INT);
$stmt->execute();
$sql1 = "SELECT * FROM feed WHERE user_id_fk=:user_id ORDER BY
feed_id DESC LIMIT 1";
$stmt1 = $db->prepare($sql1);
$stmt1->bindParam("user_id", $user_id, PDO::PARAM_INT);
$stmt1->execute();
$feedData = $stmt1->fetch(PDO::FETCH_OBJ);
$db = null;
echo '{"feedData": ' . json_encode($feedData) . '}';
} else{
echo '{"error":{"text":"No access"}}';
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
function feedDelete(){
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
$user_id=$data->user_id;
$token=$data->token;
$feed_id=$data->feed_id;
$systemToken=apiToken($user_id);
try {
if($systemToken == $token){
$feedData = '';
$db = getDB();
$sql = "DELETE FROM feed WHERE user_id_fk=:user_id AND
feed_id=:feed_id";
$stmt = $db->prepare($sql);
$stmt->bindParam("user_id", $user_id, PDO::PARAM_INT);
$stmt->bindParam("feed_id", $feed_id, PDO::PARAM_INT);
$stmt->execute();
$db = null;
echo '{"success":{"text":"Feed deleted"}}';
} else{
echo '{"error":{"text":"No access"}}';
}
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
?>
home.ts
Go to Home page component and included feedUpdate and feedDelete functions. These functions connect with feed update and delete APIs for database changes. Using unshift javascript built-in function pushing the feedUpdate result into dataSet feed object.
import {Component} from '@angular/core';
import {NavController, App, AlertController} 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": ""
};
constructor(public common : Common, public 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.getFeed();
}
getFeed() {
// feed details function
}
feedUpdate() {
if (this.userPostData.feed) {
this.common.presentLoading();
this.authService.postData(this.userPostData, "feedUpdate")
.then((result) => {
this.resposeData = result;
if (this.resposeData.feedData) {
this.common.closeLoading();
this.dataSet.unshift(this.resposeData.feedData);
this.userPostData.feed = "";
} else {
console.log("No access");
}
}, (err) => {
//Connection failed message
});
}
}
feedDelete(feed_id, msgIndex) {
if (feed_id > 0) {
let alert = this.alertCtrl.create({
title: 'Delete Feed',
message: 'Do you want to buy this feed?',
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}, {
text: 'Delete',
handler: () => {
this.userPostData.feed_id = feed_id;
this.authService.postData(this.userPostData, "feedDelete")
.then((result) => {
this.resposeData = result;
if (this.resposeData.success) {
this.dataSet.splice(msgIndex, 1);
} else {
console.log("No access");
}
}, (err) => {
//Connection failed message
});
}
}
]
});
alert.present();
}
}
}
For delete function impleted with Ionic alert controller.import {NavController, App, AlertController} 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": ""
};
constructor(public common : Common, public 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.getFeed();
}
getFeed() {
// feed details function
}
feedUpdate() {
if (this.userPostData.feed) {
this.common.presentLoading();
this.authService.postData(this.userPostData, "feedUpdate")
.then((result) => {
this.resposeData = result;
if (this.resposeData.feedData) {
this.common.closeLoading();
this.dataSet.unshift(this.resposeData.feedData);
this.userPostData.feed = "";
} else {
console.log("No access");
}
}, (err) => {
//Connection failed message
});
}
}
feedDelete(feed_id, msgIndex) {
if (feed_id > 0) {
let alert = this.alertCtrl.create({
title: 'Delete Feed',
message: 'Do you want to buy this feed?',
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}, {
text: 'Delete',
handler: () => {
this.userPostData.feed_id = feed_id;
this.authService.postData(this.userPostData, "feedDelete")
.then((result) => {
this.resposeData = result;
if (this.resposeData.success) {
this.dataSet.splice(msgIndex, 1);
} else {
console.log("No access");
}
}, (err) => {
//Connection failed message
});
}
}
]
});
alert.present();
}
}
}
Creating Pre-Loading Provider
Creating new provider using Ionic generate command. If this not working please follow my previous articles.
$ionic generate provider common
commont.ts
Imported Ionic loading controller to implemente pre-loading feature for API calls. This is the most commonly used, so that we are creating this as an injectable provider.
import { Injectable } from '@angular/core';
import { LoadingController } from 'ionic-angular';
@Injectable()
export class Common {
public loader: any;
constructor(public loadingCtrl: LoadingController) {
console.log('Hello Common Provider');
}
presentLoading(){
this.loader = this.loadingCtrl.create({content: "Please wait ..."})
this.loader.present();
}
closeLoading(){
this.loader.dismiss();
}
}
import { LoadingController } from 'ionic-angular';
@Injectable()
export class Common {
public loader: any;
constructor(public loadingCtrl: LoadingController) {
console.log('Hello Common Provider');
}
presentLoading(){
this.loader = this.loadingCtrl.create({content: "Please wait ..."})
this.loader.present();
}
closeLoading(){
this.loader.dismiss();
}
}
app.module.ts
Importing new plugins in the application module. Now go to src/app/app.module.ts and import Common for API pre-loading.
import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { AuthService } from '../providers/auth-service';
import { SplitPane } from '../providers/split-pane';
import { Common } from '../providers/common';
import { Welcome } from '../pages/welcome/welcome';
import { Login } from '../pages/login/login';
import { Signup } from '../pages/signup/signup';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { LinkyModule } from 'angular-linky';
import { MomentModule } from 'angular2-moment';
@NgModule({
declarations: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Welcome,
Login,
Signup,
TabsPage
],
imports: [
BrowserModule, HttpModule, LinkyModule, MomentModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Welcome,
Login,
Signup,
TabsPage
],
providers: [
StatusBar,
SplashScreen, AuthService, SplitPane, Common,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { AuthService } from '../providers/auth-service';
import { SplitPane } from '../providers/split-pane';
import { Common } from '../providers/common';
import { Welcome } from '../pages/welcome/welcome';
import { Login } from '../pages/login/login';
import { Signup } from '../pages/signup/signup';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { LinkyModule } from 'angular-linky';
import { MomentModule } from 'angular2-moment';
@NgModule({
declarations: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Welcome,
Login,
Signup,
TabsPage
],
imports: [
BrowserModule, HttpModule, LinkyModule, MomentModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
AboutPage,
ContactPage,
HomePage,
Welcome,
Login,
Signup,
TabsPage
],
providers: [
StatusBar,
SplashScreen, AuthService, SplitPane, Common,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
Build iOS App
Following commands for executing Xcode build, watch the video tutorial you will understand more.
$ cordova add platform ios
$ ionic build ios
$ ionic build ios
Build Android App
Open Android build using Android SDK>
$ cordova add platform android
$ ionic build android
$ ionic build android
Previous Part Video Tutorial
Ionic 3 and Angular 4 Banana APP.
nice tutorial
ReplyDeletegood tutorial
ReplyDeleteafter signup it will login automatically but before that it'll show some runtime error (screenshot: https://ibb.co/dODeU5). If I close the error the side menu with logout button and a blank home page. After clicking the logout button I tried logging in using the account that I created but it says "Please enter a valid username and password"
ReplyDeleteHi Srinivas Tamada,
ReplyDeleteYour tutorials are very useful. But I need one help I want to setup Slim Framework in my Linux share server for Application API. I search lot in google but I don't get any proper [easy] doc for setup slim framework in Linux. Please Help me.
Contact your hosting provider to enable mod_rewrite extension for .htaccess support
DeleteThanks Srinivas Tamada,
ReplyDeleteyour tutorials are just great, please can u make a tutorial on image upload along side with user post... thanks in advance...
nice post keep it up
ReplyDeleteHI, very helpfull buy i have a problem, if a send headers in a post or get api call always response error 404 but if, ut if user a curl command or other api test app return me the values please can you help me
ReplyDeleteHi, I really find your tutorials very helpful. Thanks for taking the time to share your skills.
ReplyDeleteSir this is good and very very nice tutorial
ReplyDeletecan you give any solution for this error
ReplyDeleteD:\ionic\ionic3-angular4-signaturepad-master>ionic serve
Error: Cannot find module 'D:\ionic\ionic3-angular4-signaturepad-master\node_mod
ules\@ionic\app-scripts'
at Function.Module._resolveFilename (module.js:536:15)
at Function.Module._load (module.js:466:25)
at Module.require (module.js:579:17)
at require (internal/module.js:11:18)
at Object. (C:\Users\Home\AppData\Roaming\npm\node_modules\ionic\
node_modules\@ionic\cli-utils\lib\ionic-angular\app-scripts.js:9:16)
at Generator.next ()
at C:\Users\Home\AppData\Roaming\npm\node_modules\ionic\node_modules\tslib\t
slib.js:103:75
at new Promise ()
at Object.__awaiter (C:\Users\Home\AppData\Roaming\npm\node_modules\ionic\no
de_modules\tslib\tslib.js:99:16)
at Object.importAppScripts (C:\Users\Home\AppData\Roaming\npm\node_modules\i
onic\node_modules\@ionic\cli-utils\lib\ionic-angular\app-scripts.js:7:20)
[ERROR] Error with .\node_modules\@ionic\app-scripts\package.json file:
FILE_NOT_FOUND
Delete node_modules and execute npm install
Deletehello can you give example, httpClient call with custom header parameter, I always failed the header parameter always became Access-Control-Request-Headers
ReplyDeleteThanks bro but how to update feed table using token
ReplyDelete