Ionic 3, Angular 5 and Cordova Base64 Image Upload Example

by Didin J. on May 02, 2018 Ionic 3, Angular 5 and Cordova Base64 Image Upload Example

Step by step tutorial on Ionic 3, Angular 5 and Cordova Base64 Image Upload Example

The comprehensive step by step tutorial on Ionic 3, Angular 5 and Cordova Base64 Image Upload Example. Previously, we have shown you a tutorial about uploading the file using Ionic 3, Cordova and Native File Transfer plugin. Now, we are creating file upload that saves directly to the database as a base64 Image string. The base64 Image sends to the server along with other data in the same HTML form. So, the point of this tutorial is sent or POST an HTML form that contains an Image. Image or Photo picked using Ionic 3 Cordova Image Picker Plugin then convert it to base64 Image using Ionic 3 Cordova Base64 Plugin. The base64 string hold by the model field before uploading the whole form to the REST API.

Shortcut to the steps:

The following tools, frameworks, and modules are required for this tutorial:

  1. Node.js
  2. Ionic 3
  3. Angular 5
  4. Cordova
  5. Ionic Cordova Image Picker Plugin
  6. Ionic Cordova Base64 Plugin
  7. Terminal or Command Line
  8. RESTful API
  9. IDE or Text Editor

We assume that Node.js already installed with the latest recommended for most users version. To check it, open the terminal or Node command line then type this command to check the right version.

node -v
v8.11.1
npm -v
6.0.0

The result below the command of the version that we use right now. Now, update or install Ionic 3 and Cordova with the latest version. The open terminal then goes to your Ionic 3 projects folder then type this command.

sudo npm i -D -E ionic@latest
sudo npm i g cordova


Create a New Ionic 3 and Angular 5 App

On the terminal or Node.js command line type this command to create a new Ionic 3, Angular 5 and Cordova App with the name of ionic-image-upload.

ionic start ionic-image-upload blank

You can skip Cordova integration right now, it will be added manually next time. Next, go to the newly created folder.

cd ./ionic-image-upload

For the tutorial sanitation, run the app on the browser then type this command.

ionic serve -l

That command will open the default browser and display this page.

Ionic 3, Angular 5 and Cordova Base64 Image Upload Example - Ionic 3 Blank


Install and Configure Required Plugin and Modules

As described in the first paragraph of the article that we will use Ionic 3 Cordova Image Picker and Ionic 3 Cordova Base64 Native Plugin, in the terminal type this command to install cordova-plugin-telerik-imagepicker, @ionic-native/image-picker, com.badrit-base64, and @ionic-native/base64.

ionic cordova plugin add cordova-plugin-telerik-imagepicker --variable PHOTO_LIBRARY_USAGE_DESCRIPTION="your usage message"
npm install --save @ionic-native/image-picker
ionic cordova plugin add com-badrit-base64
npm install --save @ionic-native/base64

Next, open and edit `src/app/app.module.ts` then add these imports of ImagePicker (@ionic-native/image-picker) and Base64 (@ionic-native/base64).

import { ImagePicker } from '@ionic-native/image-picker';
import { Base64 } from '@ionic-native/base64';

Register the Image Picker and Base64 to the `@NgModule` providers, so the whole providers will look like this.

providers: [
  StatusBar,
  SplashScreen,
  {provide: ErrorHandler, useClass: IonicErrorHandler},
  ImagePicker,
  Base64
]


Create an Ionic 3 Angular 5 Register Form

We have to create an Ionic 3 and Angular 5 register form that includes Base64 Image upload. Inside the form, there is an Image preview with a default dummy image. If we click on the image it will run Image Picker. Open and edit default `src/pages/home/home.html` then replace all HTML tags with this Angular NgForm.

<ion-header>
  <ion-navbar>
    <ion-title>
      Register
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <form (ngSubmit)="register()" #regForm="ngForm">
    <ion-list>
      <ion-item>
        <ion-label fixed>Avatar</ion-label>
        <ion-avatar item-end>
          <img src="{{imgPreview}}" (click)="getPhoto()">
        </ion-avatar>
      </ion-item>
      <ion-item>
        <ion-label fixed>Email</ion-label>
        <ion-input type="email" [(ngModel)]="regData.email" name="email" required></ion-input>
      </ion-item>
      <ion-item>
        <ion-label fixed>Password</ion-label>
        <ion-input type="password" [(ngModel)]="regData.password" name="password" required></ion-input>
      </ion-item>
      <ion-item>
        <ion-label fixed>Full Name</ion-label>
        <ion-input type="text" [(ngModel)]="regData.fullname" name="fullname" required></ion-input>
      </ion-item>
    </ion-list>
    <div padding>
      <button ion-button full [disabled]="regForm.invalid">Register</button>
    </div>
  </form>
</ion-content>

Next, open and edit `src/pages/home/home.ts` then add these imports of ImagePicker (@ionic-native/image-picker) and Base64 (@ionic-native/base64).

import { ImagePicker } from '@ionic-native/image-picker';
import { Base64 } from '@ionic-native/base64';

Inject that plugins to the constructor params.

constructor(public navCtrl: NavController,
  private imagePicker: ImagePicker,
  private base64: Base64) {}

Add these variables before the constructor.

regData = { avatar:'', email: '', password: '', fullname: '' };
imgPreview = 'assets/imgs/blank-avatar.jpg';

Create the function for getting photo file and convert it to base64, also it will show or preview by replacing the default dummy image.

getPhoto() {
  let options = {
    maximumImagesCount: 1
  };
  this.imagePicker.getPictures(options).then((results) => {
    for (var i = 0; i < results.length; i++) {
        this.imgPreview = results[i];
        this.base64.encodeFile(results[i]).then((base64File: string) => {
          this.regData.avatar = base64File;
        }, (err) => {
          console.log(err);
        });
    }
  }, (err) => { });
}


POST the Register Form to REST API

After the form settles up, we have to POST it to the REST API. First, we have to add Angular `HttpClient` module to the app. Open and edit `src/app/app.module.ts` then add this import of HttpClientModule (@angular/common/http).

import { HttpClientModule } from '@angular/common/http';

Add it to `@NgModule` imports after the Browser Module.

imports: [
  BrowserModule,
  HttpClientModule,
  IonicModule.forRoot(MyApp)
],

Next, we have to create providers for handling REST API requests. Type this command to create it.

ionic g provider api

Open and edit `src/providers/api/api.ts` then add or modify these imports of HttpClient, HttpHeaders (@angular/common/http), Observable (RxJS), and map (RxJS Operators).

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators';

Add this function to extract the response data.

private extractData(res: Response) {
  let body = res;
  return body || { };
}

Declare a variable for hold REST API URL before the `@Injectable`.

let apiUrl = 'http://192.168.0.7:3000/';

Create a constant object for HTTP Headers after URL variable.

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

You can specify your own REST API URL. Next, add the function for POST registration data.

register(data): Observable<any> {
  return this.http.post(apiUrl+'users', JSON.stringify(data), httpOptions);
}

Add a function to get user data.

getUser(id): Observable<any> {
  return this.http.get(apiUrl+'users/'+id, httpOptions).pipe(
    map(this.extractData));
}

Next, open and edit `src/pages/home/home.html` then add or modify these imports of NavController, AlertController, LoadingController (ionic-angular), and ApiProvider.

import { NavController, AlertController, LoadingController } from 'ionic-angular';
import { ApiProvider } from '../../providers/api/api';

Inject to the constructor.

constructor(public navCtrl: NavController,
  private imagePicker: ImagePicker,
  private base64: Base64,
  public api: ApiProvider,
  public loadingCtrl: LoadingController,
  public alertCtrl: AlertController) {}

Add a variable for hold loading spinner component.

loading: any;

Add this function to show loading spinner when POST to the REST API.

showLoader(){
  this.loading = this.loadingCtrl.create({
      content: 'Submitting...'
  });

  this.loading.present();
}

Next, add a function for submitting the registration form.

register() {
  this.showLoader();
  this.api.register(this.regData).subscribe((result) => {
    this.loading.dismiss();
    let alert = this.alertCtrl.create({
      title: 'Registration Successful',
      subTitle: 'Great! Your registration is success',
      buttons: ['OK']
    });
    alert.present();
  }, (err) => {
    console.log(err);
    this.loading.dismiss();
    let alert = this.alertCtrl.create({
      title: 'Registration Failed',
      subTitle: 'Oh no! Your registration is failed',
      buttons: ['OK']
    });
    alert.present();
  });
}


Get User Data from REST API

We need to show the posted user data after registration successful. For that, create a new Ionic 3 Angular 5 page for display the user data by type this command.

ionic g page detail

Register the new page to `src/app/app.module.ts` by adding this import.

import { DetailPage } from '../pages/detail/detail';

Then add to `@NgModule` declarations and `entryComponents`.

declarations: [
  MyApp,
  HomePage,
  DetailPage
],
...
entryComponents: [
  MyApp,
  HomePage,
  DetailPage
],

Before modifying the new page, open and edit `src/pages/home/home.ts` to add the import for Detail Page.

import { DetailPage } from '../detail/detail';

Modify the register function to add action after a successful registration.

register() {
  this.showLoader();
  this.api.register(this.regData).subscribe((result) => {
    this.loading.dismiss();
    let alert = this.alertCtrl.create({
      title: 'Registration Successful',
      subTitle: 'Great! Your registration is success',
      buttons: [
        {
          text: 'OK',
          handler: () => {
            this.navCtrl.push(DetailPage, {id:result._id});
          }
        }
      ]
    });
    alert.present();

  }, (err) => {
    console.log(err);
    this.loading.dismiss();
    let alert = this.alertCtrl.create({
      title: 'Registration Failed',
      subTitle: 'Oh no! Your registration is failed',
      buttons: ['OK']
    });
    alert.present();
  });
}

Next, open and edit `src/pages/detail/detail.html` then replace all HTML tags with this <ion-card>.

<ion-header>

  <ion-navbar>
    <ion-title>User Detail</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>
  <ion-card>
    <img [src]="user.avatar"/>
    <ion-card-content>
      <ion-card-title>{{user.fullname}}</ion-card-title>
      <p>
        {{user.email}}
      </p>
    </ion-card-content>
  </ion-card>
</ion-content>

Open and edit `src/pages/detail/detail.ts` then add or modify these imports of IonicPage, NavController, NavParams, LoadingController (ionic-angular), ApiProvider, and DomSanitizer (@angular/platform-browser).

import { IonicPage, NavController, NavParams, LoadingController } from 'ionic-angular';
import { ApiProvider } from '../../providers/api/api';
import { DomSanitizer } from '@angular/platform-browser';

Delacre these variables before the constructor.

user = {};
id:any;
loading:any;

Add required modules to the constructor and get parameter that gets from Home Page.

constructor(public navCtrl: NavController,
  public navParams: NavParams,
  public api: ApiProvider,
  public loadingCtrl: LoadingController,
  private sanitizer: DomSanitizer) {
  this.id = navParams.get("id");
}

Add the function to show the loading spinner.

showLoader(msg){
  this.loading = this.loadingCtrl.create({
      content: msg
  });

  this.loading.present();
}

Add function for getting User Detail by user ID.

getUser(id) {
  this.showLoader("Loading...");
  this.api.getUser(id)
    .subscribe(data => {
      this.user = {
        email: data.email,
        fullname: data.fullname,
        avatar: this.sanitizer.bypassSecurityTrustResourceUrl(data.avatar)
      };
      this.loading.dismiss();
    }, err => {
      console.log(err);
      this.loading.dismiss();
    });
}

Call that function inside `ionViewDidLoad`.

ionViewDidLoad() {
  this.getUser(this.id);
}


Run and Test The Complete Ionic 3, Angular 5 and Cordova App

Before running the complete Ionic 3, Angular 5 and Cordova App to the device, remove or add the Cordova iOS and Android platform first by type this command.

ionic cordova platform rm ios
ionic cordova platform add ios
ionic cordova platform rm android
ionic cordova platform add [email protected]

We use Cordova-Android version 6.3.0 because of the latest version 7.0.0 too many bugs. Also for iOS, we have to disable WKWebView before run it to the device by type this command.

ionic cordova plugin rm cordova-plugin-ionic-webview

Otherwise, this error will happen when running this app to the device.

{"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":null,"ok":false,"name":"HttpErrorResponse","message":"Http failure response for (unknown url): 0 Unknown Error","error":{"isTrusted":true}}
2018-05-02 20:45:51.503 Base64 Upload[59179:6264130] CDVWKWebViewEngine: handleStopScroll

Now, you can run to the real device.

ionic cordova run android
ionic cordova run ios

And here's the app looks like.

Ionic 3, Angular 5 and Cordova Base64 Image Upload Example - Home Page
Ionic 3, Angular 5 and Cordova Base64 Image Upload Example - Successful registration
Ionic 3, Angular 5 and Cordova Base64 Image Upload Example - Show user detail

That it's, the comprehensive step by step tutorial on Ionic 3, Angular 5 and Cordova Base64 Image Upload Example. Don't worry, you can compare the tutorial to the working source code in our GitHub.

We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 4 - Full Starter App and save development and design time. Android, iOS, and PWA, 100+ Screens and Components, the most complete and advance Ionic Template.

That just the basic. If you need more deep learning about Ionic, Angular, and Typescript, you can take the following cheap course:

Thanks!