Signing business contract
Close-up of businessman signing a contract at the table during a business meeting

Signature pad is one of the most important things of every day web application or mobile application. Here, I am going to explain how to capture the signature pad data and how to upload to the server

First of all, start a new project using ionic CLI command.

ionic start signature_pad blank

Once your project successfully, then install the ionic native file plugin using the following comments

ionic cordova plugin add cordova-plugin-file
npm install @ionic-native/file

Next, import the camera and File into your app module and inject into the provider section. Now, your app module file should like this

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';
import { File } from '@ionic-native/file/ngx';
import {HttpClientModule} from '@angular/common/http';@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule
],
providers: [
StatusBar,
SplashScreen,
File,
{
provide: RouteReuseStrategy,
useClass: IonicRouteStrategy
}
],
bootstrap: [AppComponent]
})
export class AppModule {}

Next, generate a service using ionic CLI command, using the following command for creating a service.

ionic g service Upload

Import HttpClientModule into your app module and inject it into the imports section. (Please refer the above code)

Your service file source code will like the following

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';@Injectable({
providedIn: 'root'
})
export class UploadService { constructor(private http: HttpClient) { } uploadFile(formData) {
return this.http.post('https://example.com/upload.php', formData);
}
}

Your home component scss file like the following

.signature-pad {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
font-size: 10px;
width: 100%;
height: 100%;
max-width: 700px;
max-height: 460px;
border: 1px solid #e8e8e8;
background-color: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset;
border-radius: 4px;
padding: 16px;
}

.signature-pad--body {
position: relative;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
border: 1px solid #f4f4f4;
}

Your home component template file like the following

<ion-header>
<ion-toolbar>
<ion-title>
SignaturePad
</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<div class="ion-padding">
<div class="signature-pad">
<div class="signature-pad--body">
<canvas #sPad width="900" height="863" style="touch-action: none;"></canvas>
</div>
</div>
</div>
<ion-row>
<ion-col>
<ion-button color="primary" (click)="save()">Save</ion-button>
</ion-col>
<ion-col>
<ion-button color="primary" (click)="clear()">Clear</ion-button>
</ion-col>
</ion-row>
{{res | json}}
</ion-content>

your home component class file like the following

import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
import SignaturePad from 'signature_pad';
import {File, IWriteOptions, FileEntry} from '@ionic-native/file/ngx';
import {UploadService} from '../upload.service';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit, AfterViewInit {
@ViewChild('sPad', {static: true}) signaturePad;
signPad: any;
res: any;
options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
};
constructor(private file: File, private uploadService: UploadService) {}

ngOnInit(): void {
}

ngAfterViewInit(): void {
this.signPad = new SignaturePad(this.signaturePad.nativeElement);
}

dataURLToBlob(dataURL) {
// Code taken from https://github.com/ebidel/filer.js
const parts = dataURL.split(';base64,');
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}

save() {
const dataUrl = this.signPad.toDataURL();
const blob = this.dataURLToBlob(dataUrl);
const name = new Date().getTime() + '.png';
const path = this.file.dataDirectory;
const options: IWriteOptions = { replace: true };
this.file.writeFile(path, name, blob, options).then(res => {
this.res = res;
this.file.resolveLocalFilesystemUrl(res.nativeURL).then((entry: FileEntry) => {
entry.file(file => {
console.log(file);
this.readFile(file);
});
});
console.log(this.res);
});
}

clear() {
this.signPad.clear();
}

readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const imgBlob = new Blob([reader.result], {
type: file.type
});
const formData = new FormData();
formData.append('name', 'Hello');
formData.append('file', imgBlob, file.name);
this.uploadService.uploadFile(formData).subscribe(dataRes => {
console.log(dataRes);
});
};
reader.readAsArrayBuffer(file);
}
}

in this code we are using the method dataURLToBlob for converting the file base64 image data into blob format. Here we are using ionic native file plugin to store the file into our local. we are using writeFile method to save the file. once the file saved successfully. we are using the resolveLocalFilesystemUrl method to load the local file to upload. the readFile method load the file data and convert to it into the multi-part upload file format. the we calling the upload service to upload the data to server.

the PHP server side script will like the following

<?php
$name = $_POST['name'];
if($_FILES['file']){
$path = 'uploads/';
if (!file_exists($path)) {
mkdir($path, 0777, true);
}
$originalName = $_FILES['file']['name'];
$ext = '.'.pathinfo($originalName, PATHINFO_EXTENSION);
$t=time();
$generatedName = md5($t.$originalName).$ext;
$filePath = $path.$generatedName;
if (move_uploaded_file($_FILES['file']['tmp_name'], $filePath)) {
echo json_encode(array(
'result' => 'success',
'status' => true,
));
}
}
?>

For more tutorials please visit y official website

If need video tutorial, please subscribe my YouTube channel