In this modernized version, we’ll build a native-like mobile app using Ionic 8, Angular 20, and Capacitor 5, walking through how to:
-
Generate PDFs from HTML content using jsPDF or pdfMake
-
Download and store PDF files using Capacitor’s
Filesystem
-
Open and preview the PDF using
@capacitor-community/file-opener
This replaces the legacy Cordova-based dom-to-image
+ File Opener – going fully Capacitor‑native.
Step 1: Project Setup
To create a new Ionic Angular app, type this command.
npm install -g @ionic/cli
ionic start ionic-pdf-export blank --type=angular
You will see questions during the installation, just choose the default. Next, go to the newly created app folder.
cd ionic-pdf-export
Install all required modules and dependencies.
ionic integrations enable capacitor
npm install jspdf pdfmake @capacitor/filesystem @capacitor-community/file-opener
npm i --save-dev @types/pdfmake
npm run build
npx cap sync
For sanitizing, run the app on the browser for the first time to make sure everything is working properly.
ionic serve
Now, the browser will open automatically then you will see this Ionic page using Chrome inspect device mode.
Step 2: Create PDF Generation Service
Generate pdf.service.ts
.
ionic g service services/pdf
Update it with this.
import { Injectable } from '@angular/core';
import jsPDF from 'jspdf';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
@Injectable({ providedIn: 'root' })
export class PdfService {
constructor() { pdfMake.vfs = pdfFonts.vfs; }
generateWithJsPDF(html: string): jsPDF {
const doc = new jsPDF({
format: 'a4',
unit: 'pt',
});
doc.html(html, {
callback: () => { },
x: 10, y: 10
});
return doc;
}
generateWithPdfMake(content: any) {
return pdfMake.createPdf({ content });
}
}
Step 3: Download and Save the PDF on the Device
Generate file.service.ts
.
ionic g service services/file
Update it with this.
import { Injectable } from '@angular/core';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import { FileOpener } from '@capacitor-community/file-opener';
@Injectable({ providedIn: 'root' })
export class FileService {
async saveAndOpenPdf(base64: string, fileName = 'document.pdf') {
const result = await Filesystem.writeFile({
path: `mypdfs/${fileName}`,
data: base64,
directory: Directory.Documents,
encoding: Encoding.UTF8
});
await FileOpener.open({ filePath: result.uri, contentType: 'application/pdf' });
}
}
Step 4: Integrate into a Page
Update src/app/home/home.page.ts
:
import { Component, ElementRef, ViewChild } from '@angular/core';
import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton } from '@ionic/angular/standalone';
import { PdfService } from '../services/pdf.service';
import { FileService } from '../services/file.service';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonButton, IonContent],
})
export class HomePage {
@ViewChild('invoiceContent', { static: false }) content!: ElementRef;
today = new Date().toLocaleDateString();
constructor(private pdf: PdfService, private file: FileService) { }
async exportPdf() {
const html = this.content.nativeElement.innerHTML;
const doc = this.pdf.generateWithJsPDF(html);
const base64 = doc.output('datauristring');
const trimmed = base64.split(',')[1];
await this.file.saveAndOpenPdf(trimmed, `invoice_${Date.now()}.pdf`);
}
}
Update src/app/home/home.page.html
:
<ion-header
><ion-toolbar><ion-title>Export PDF</ion-title></ion-toolbar></ion-header
>
<ion-content class="ion-padding">
<div #invoiceContent>
<h2>Invoice</h2>
<p>Date: {{ today }}</p>
<table border="1" cellpadding="8" cellspacing="0" width="100%">
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Web Design</td>
<td>1</td>
<td>$500</td>
<td>$500</td>
</tr>
<tr>
<td>Hosting (1 Year)</td>
<td>1</td>
<td>$100</td>
<td>$100</td>
</tr>
<tr>
<td>Domain Name</td>
<td>1</td>
<td>$15</td>
<td>$15</td>
</tr>
<tr>
<td colspan="3" align="right"><strong>Total</strong></td>
<td><strong>$615</strong></td>
</tr>
</tbody>
</table>
</div>
<ion-button expand="block" (click)="exportPdf()"
>Export & View PDF</ion-button
>
</ion-content>
Step 5: Testing
1. Run in browser: ionic serve
to test generation (filesystem won’t work here).
2. Run on device/emulator:
ionic build
npx cap sync
npx cap run android
3. Tap Export & View PDF → PDF should generate, download, and open in the device's PDF viewer.
ionic cordova run ios
ionic cordova run android
You should see this page when it's running successfully.
Optional Enhancements
-
Display download progress using
Filesystem.downloadFile(...)
per the Capacitor docs. -
Switch to
pdfMake
for rich, structured PDF layouts. -
Configure iOS permissions if needed for file access.
-
Add production polish: dynamic filenames, error handling, UI feedback.
Summary
-
Dependencies: jsPDF / pdfMake + Capacitor Filesystem + File Opener
-
No Cordova plugins. Fully native to Capacitor
-
Modern stack: Ionic 8, Angular 20, Capacitor 5
You can find the working source code on our GitHub.
We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 6 - Full Starter App and save development and design time. Android, iOS, and PWA, 100+ Screens and Components, the most complete and advanced Ionic Template.
That's just the basics. If you need more deep learning about Ionic, Angular, and TypeScript, you can take the following cheap course:
- Ionic Apps with Firebase
- Ionic Apps for WooCommerce: Build an eCommerce Mobile App
- Ionic 8+: Build Food Delivery App from Beginner to Advanced
- IONIC - Build Android & Web Apps with Ionic
- Full Stack Development with Go, Vuejs, Ionic & MongoDB
- Create a Full Ionic App with Material Design - Full Stack
Thanks!