ngx-pdfium-viewer
v0.2.0
Published
Angular PDF viewer built on PDFium (WASM): pinch-zoom, search, links, form fields and thumbnails, tuned for mobile WebViews.
Downloads
44
Maintainers
Readme
ngx-pdfium-viewer
Angular PDF viewer built on PDFium compiled to WebAssembly via @embedpdf/pdfium. Renders directly to canvas — no pdf.js, no iframe.
- Pinch-zoom with focal-point precision, bounded two-finger pan, fit-width floor
- Lazy page rendering with scroll-aware batching for long documents
- Text search with highlight overlays
- Clickable links (URI, internal goto, launch)
- AcroForm text fields: view, edit, save the filled PDF
- Thumbnail sidebar, print, download
- Tuned for Ionic/Capacitor WebViews (iOS canvas-memory limits, Android touch)
Requires Angular 20+.
Install
npm install ngx-pdfium-viewer @embedpdf/pdfiumShip the WASM binary
PDFium runs from a .wasm file that your app must serve. Add this to the assets array of your build target in angular.json (both build and test if present):
{
"glob": "pdfium.wasm",
"input": "node_modules/@embedpdf/pdfium/dist",
"output": "assets/pdfium"
}The viewer fetches assets/pdfium/pdfium.wasm by default. To serve it from somewhere else (a CDN, a different path), provide the URL:
import { providePdfiumWasmUrl } from 'ngx-pdfium-viewer';
bootstrapApplication(AppComponent, {
providers: [providePdfiumWasmUrl('https://cdn.example.com/pdfium.wasm')],
});Two ways to use it
| import | what you get | extra peers |
|---|---|---|
| ngx-pdfium-viewer | PdfiumComponent — the viewer surface, no chrome | none |
| ngx-pdfium-viewer/ionic | PdfiumShellComponent — a complete screen: nav bar, tool bar, find bar, page HUD, loading overlay | @ionic/angular >=9, ionicons, @angular/forms |
Reach for the shell if you want a working viewer out of the box, and for
PdfiumComponent if you are building your own chrome.
The ready-made screen
npm install ngx-pdfium-viewer @embedpdf/pdfium @ionic/angular ioniconsimport { Component } from '@angular/core';
import { PdfiumShellComponent } from 'ngx-pdfium-viewer/ionic';
@Component({
selector: 'app-reader',
imports: [PdfiumShellComponent],
template: `
<ngx-pdfium-shell
src="assets/manual.pdf"
documentTitle="Manual"
backHref="/home"
(linkClicked)="onLink($event)"
></ngx-pdfium-shell>
`,
})
export class ReaderComponent {
onLink(url: string) { /* … */ }
}The shell needs Ionic 9 or newer: it imports Ionic's standalone components from
the @ionic/angular root, which on Ionic 8 is still the NgModule build.
Shell inputs
| input | type | notes |
|---|---|---|
| src | string (required) | URL of the PDF to load |
| documentTitle | string | Shown in the nav bar and on the loading overlay |
| backHref | string \| null | Back-button target; leave unset to hide the button |
| paddingTop / paddingBottom | string | Insets inside the scroll area; defaults clear the header and the floating page HUD |
| openLinks | boolean | Whether to window.open a clicked link. Set false when you handle linkClicked yourself |
Shell outputs
| output | payload |
|---|---|
| linkClicked | string URI — always emitted, whatever openLinks is set to |
| pageCountReady | number |
| currentPageChanged | number (0-based) |
To open links with Capacitor's in-app browser instead of a new tab:
<ngx-pdfium-shell src="assets/manual.pdf" [openLinks]="false" (linkClicked)="open($event)" />The entry point also exports each bar (PdfNavBarComponent, PdfActionBarComponent,
PdfFindBarComponent, PdfPageHudComponent, PdfLoadingOverlayComponent) and the
controllers behind them, for hosts that want to compose a different layout. Each bar
resolves its controllers through DI, so it must sit inside a component that provides
them — see PdfiumShellComponent for the arrangement.
Use the viewer directly
PdfiumComponent is standalone.
import { Component } from '@angular/core';
import { PdfiumComponent } from 'ngx-pdfium-viewer';
@Component({
selector: 'app-reader',
imports: [PdfiumComponent],
template: `
<ngx-pdfium-viewer
[src]="'assets/manual.pdf'"
[searchTerm]="term"
(onPageCountReady)="pages = $event"
(onCurrentPageChanged)="current = $event"
(onLinkClicked)="open($event)"
></ngx-pdfium-viewer>
`,
})
export class ReaderComponent {
term = '';
pages = 0;
current = 0;
open(url: string) { window.open(url, '_blank'); }
}In an NgModule-based app, add PdfiumComponent to the module's imports (not declarations).
Inputs
| input | type | notes |
|---|---|---|
| src | string (model) | URL of the PDF to load |
| searchTerm | string | Highlights every match; empty clears |
| searchIndex | number (model) | Active match, 0-based |
| paddingTop / paddingBottom | string | CSS length applied inside the scroll area — for toolbars, safe-area insets |
Outputs
| output | payload |
|---|---|
| onProgress | number 0..1 while loading |
| onPageCountReady | number |
| onCurrentPageChanged | number (0-based) |
| onInitialPagesRendered | — first batch on screen |
| onSearchInfoChanged | SearchInfo { searchTerm, index, total } |
| onLinkClicked | string URI |
| onFormFieldsReady | number fields found |
| onThumbnailsChanged | boolean sidebar open |
| onClick | PointerEvent tap on the page (not on a link or field) |
Methods (via viewChild)
zoomIn(), zoomOut(), onZoomChange(scale), applyFitWidth(), scrollToPage(i), goToNextPage(), goToPreviousPage(), navigateToMatch(i), highlightWord(word), clearHighlights(), toggleThumbnails(), setFormFieldValuesInPdf(values), getFilledPdfBytes(), savePdf(), printPdf(), extractLinks().
Memory on iOS
WebKit caps canvas memory at roughly 256 MB. The viewer caps device pixel ratio at 2, allocates page bitmaps lazily, and releases them on destroy. If you open many large documents in one session, destroy the component between them rather than swapping src.
Build and publish
The library is built from source, then published from dist/:
npm login
ng build ngx-pdfium-viewer
cd dist/ngx-pdfium-viewer && npm publishpublishConfig.access is public. Unscoped packages are public by default, so this
is belt-and-braces — it keeps the publish public if the package is ever scoped.
