ionic 4 tutorial for beginners
ionic 4 tutorial for beginners
ionic 4 tutorial for beginners

Thinking about Learn Ionic 4 in just 30 mins? . I can help you to learn ionic 4 by building a photo sharing app with following features.

What you’ll learn?

This article, you’re going to create a photo sharing app with following features

Pages:

  • Home Page: Where you can see all photo feed & upload option
  • Details Page with social sharing option

Plugins:

Web Service:

  • HTTP POST & GET
  • Upload images

Navigation

  • Navigation with Angular Router
ionic 4 photo sharing app
ionic 4 photo sharing app

Getting started with ionic 4

Note: If you’re creating an ionic app for first-time, please visit: for installation help. once you completed installation then you can start here.

Let’s start by creating a new ionic project & add all required plugins and npm dependencies

ionic start photosharing
cd photosharing

Adding Required plugins: We need camera plugin for accessing device gallery, file transfer plugin for uploading image to remote server. social sharing plugin for sharing content to third-party social apps

ionic cordova plugin add cordova-plugin-camera
npm install @ionic-native/camera
ionic cordova plugin add cordova-plugin-x-socialsharing
npm install @ionic-native/social-sharingionic cordova plugin add cordova-plugin-filetransfer
npm install @ionic-native/file-transfer
Working with app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

// Added Plugins
import { Camera } from '@ionic-native/camera/ngx';
import { FileTransfer } from '@ionic-native/file-transfer/ngx';
import { SocialSharing } from '@ionic-native/social-sharing/ngx';
// Added HttpModule
import { HttpModule } from '@angular/http';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule,
HttpModule // Added HttpModule
],
  providers: [
    StatusBar,
    SplashScreen,
// Added Plugins
    Camera,
    FileTransfer,
    SocialSharing,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Explanation: Since we added plugins, we need to declare those plugin dependencies in app.module.ts; otherwise it won’t work on your project. also i have added HttpModule in order to work with Http Requests

Working with home page

We’re going to create a home page for displaying feeds & fab button for uploading images with popup alert with input (for entering image title). In order to work with that, first we need to declare all dependencies and create object for that

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { Router } from '@angular/router';
import { AlertController } from '@ionic/angular';

// Native Plugins for accessing device speific features

import { Camera } from '@ionic-native/camera/ngx';
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer/ngx';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  posts: any = [];
  url = "http://192.168.1.2:8888/test/";
  constructor(public http: Http, public route: Router, public camera: Camera, public ft: FileTransfer, public alert: AlertController) { }

  ngOnInit() {
    this.getFeed()
  }
}

Explanation: Here we have declare AlertController, Camera, FileTransfer, Http & we also created object for those in constructor. We also created two variables called posts (empty array) & url. where, ngOnInit() helps you call any function once page is initiated. Here we have called this.getFeed()

Where getFeed() fetches all data from url & assigned results into this.posts variable.

getFeed() {
  this.posts = [];
  this.http.get(this.url + "api.php/records/photos").subscribe(data => {
    let res = JSON.parse(data["_body"]);
    this.posts = res.records;
  })
}

Once http request is completed, this.post will contain all objects which is received from server. Let’s display these posts into users by using cards. In home.page.html, we have created ion-card with *ngFor

<ion-card *ngFor="let post of posts" (click)="goDetail(post)">
  <img src="{{post.path}}">
  <ion-card-header>
    <ion-card-title>{{post.title}}</ion-card-title>
    <p>{{post.created_at}}</p>
  </ion-card-header>
</ion-card>

Now, we display image, created date, title from http request to user. when user click single card, we’re getting post (JSON) variable & pass to goDetails().

goDetail(post) {
  this.route.navigate(['/details', post])
}

Here, we have used route.navigate() helps you to pass data to desired page. here we have passed our data to /details with post content.

Uploading images:

To upload images, we use camera plugin & file-transfer-plugin. Since we already added plugin, we can directly write code

Let’s add <ion-fab-button> on bottom right corner

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
  <ion-fab-button (click)="openImagePicker()">
    <ion-icon name="cloud-upload"></ion-icon>
  </ion-fab-button>
</ion-fab>

when user click this button, we need to open device gallery, so we need to create openImagePicker()

openImagePicker() {
  this.camera.getPicture({
    sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
    destinationType: this.camera.DestinationType.FILE_URI,
    quality: 50
  }).then(img => {
    this.uploadImageToServer(img);
  }).catch(err => console.log(err));
}

Explanation: this.camera.getPicture() allows you to access device camera / gallery. Here we have passed few options such as sourceType (from where you want to pick image? camera or gallery). destinationType defines how output should return & quality of image.

once, we got url of picked image, we’re passing that url to uploadImageToServer()

uploadImageToServer(img) {
  let ftObj: FileTransferObject = this.ft.create();
  ftObj.upload(img, this.url + "upload.php").then(uploadRes => {
    if (uploadRes.response != "error")
      this.insertData(uploadRes.response)
  }).catch(uploadErr => console.log(uploadErr))
}

Explanation: Here we use file transfer plugin to post image data to upload.php. Once file is uploaded to server, we’re displaying simple alert for getting image title from user.

After user input, we’re posting our data such as title, uploaded image path to /api.php/records/posts using http POST

async insertData(filepath) {
  const alert = await this.alert.create({
    message: 'Enter Name',
    inputs: [{ name: 'filename', type: 'text' }],
    buttons: [{
      text: 'ok',
      handler: (data) => {
        this.http.post(this.url + "api.php/records/photos", { "title": data.filename, "path": this.url+"uploads/"+filepath }).subscribe(data => {
          this.getFeed();
        });
      }
    }]
  })
  await alert.present();
}

Working with Details page

Details page used for display images and social sharing option. Also we need to receive data from home page using ActivatedRoute.

Let’s import & create objects for ActivatedRoute & Social Sharing

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SocialSharing } from '@ionic-native/social-sharing/ngx';

@Component({
  selector: 'app-details',
  templateUrl: './details.page.html',
  styleUrls: ['./details.page.scss'],
})
export class DetailsPage implements OnInit {
  post: any = {};
  constructor(public route: ActivatedRoute, public sharer: SocialSharing) {}
  ngOnInit() {}
}

After import, we need to receive data from home page & assign received data to post variable. so here we have used route.params.subscribe to achieve that

constructor(public route: ActivatedRoute, public sharer: SocialSharing) { 
  this.route.params.subscribe( data=> this.post = data);
}

Once data is assigned to post variable, now we can display in details.page.html & we can also created a button for share option

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>{{post.title}}</ion-title>
  </ion-toolbar>
</ion-header>
<ion-content padding>
  <img src="{{post.path}}">
  <p>Created At: {{post.created_at}}</p>
</ion-content>
<ion-footer>
  <ion-button expand="block" (click)="share()">Share</ion-button>
</ion-footer>
When user click share button, we called this.sharer.share()
share(){
  this.sharer.share(this.post.title,null,null, this.post.path);
}

Server side code

upload.php: which receives data from app & move that file into uploads folder

<?php
    header('Access-Control-Allow-Origin: *');
    $new_image_name = time()."-".urldecode($_FILES["file"]["name"]);
    if(move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/".$new_image_name)){
        echo $new_image_name;
    }
    else{
        echo "error";
    }
?>

for API, I have used https://github.com/mevdschee/php-crud-api

SQL Table: Here i have created photos table with id, title, path, created_at

CREATE TABLE `photos` (
  `id` int(11) NOT NULL,
  `title` varchar(500) NOT NULL,
  `path` varchar(500) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `photos` ADD PRIMARY KEY (`id`);

ALTER TABLE `photos` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
Please login to download source code Login Here

That’s it

Hope you enjoy this article, If you’re facing any issue, feel free to comment below

Sundaravel M

About the author: Hi! I'm Sundaravel (codesundar), Founder of codesundar.com. I have been a Web, Mobile App developer, Author, and Teacher since 2014. I also worked as a software consultant for fortune 500 companies. I created codesundar.com to share my real-time knowledge in various technologies such as PhoneGap, Ionic, Flutter and more.