Ionic 8 & Angular 20 with Capacitor: Export and View PDF Files

by Didin J. on Jul 20, 2025 Ionic 8 & Angular 20 with Capacitor: Export and View PDF Files

Learn how to generate, download, and view PDF files in an Ionic 8/Angular 20 app using Capacitor 5 and modern PDF libraries—no Cordova required.

In this modernized version, we’ll build a native-like mobile app using Ionic 8, Angular 20, and Capacitor 5, walking through how to:

  1. Generate PDFs from HTML content using jsPDF or pdfMake

  2. Download and store PDF files using Capacitor’s Filesystem

  3. 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.

Ionic 8 & Angular 20 with Capacitor: Export and View PDF Files - Ionic Serve


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.

Ionic 4, Angular 6 and Cordova: Export and View PDF File - Invoice page
Ionic 4, Angular 6 and Cordova: Export and View PDF File - PDF result


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:

Thanks!