The most reliable, feature-rich Angular PDF viewer component powered by Mozilla's PDF.js
Live Demo β’ API Reference β’ Examples β’ Server Examples β’ Migration Guide
ng2-pdfjs-viewer is the most comprehensive and feature-rich Angular PDF viewer component available. Born in 2018 and still going strong with over 7+ million downloads, this battle-tested library has been trusted by developers worldwide for over 8 years, powering thousands of applications.
This powerful library enables developers to seamlessly integrate PDF viewing capabilities into Angular applications with enterprise-grade features, custom theming, and mobile-first responsive design. Built on Mozilla's PDF.js v5.3.93, ng2-pdfjs-viewer provides advanced PDF rendering, document navigation, search functionality, and extensive customization options.
Whether you need a simple embedded PDF viewer or a complex document management system, this component delivers the performance and flexibility required for modern Angular applications. The most mature and reliable Angular PDF viewer solution with continuous updates and long-term support.
- π Always Up-to-Date - Continuously updated with the latest PDF.js versions and Angular compatibility
- ποΈ Enterprise-Ready - Built for production with comprehensive error handling and performance optimization
- π¨ Highly Customizable - Extensive theming options, custom templates, and flexible configuration
- π± Mobile Optimized - Touch-friendly interface with responsive design for all screen sizes
- π§ Developer Friendly - Full TypeScript support, comprehensive documentation, and easy integration
- β‘ High Performance - Event-driven architecture with efficient memory management and lazy loading
- π Global Support - Multi-language support with automatic locale detection and RTL compatibility
- π‘οΈ Production Tested - Trusted by thousands of applications with millions of downloads
- π Proven Track Record - 8+ years of continuous development and community support
- π Security Focused - Regular security updates and vulnerability patches
Feature | Description | Status |
---|---|---|
Advanced Theme System | CSS custom properties for complete visual customization | β New |
Template-Based UI | Custom loading spinners and error displays using Angular templates | β New |
Convenience Configuration | Object-based configuration for cleaner, more maintainable code | β New |
Event-Driven Architecture | Pure event-based system with universal action dispatcher | β New |
Enhanced Error Handling | Multiple error display styles with custom templates | β New |
Mobile-First Design | Responsive layout optimized for touch devices | β New |
TypeScript Strict Mode | Full type safety with comprehensive API coverage | β New |
- Universal Action Dispatcher - Single pathway for all actions with readiness validation
- Template-Based Customization - Use Angular templates for loading and error states
- Comprehensive Event System - 24+ events covering all user interactions and state changes
- Advanced Configuration Objects - Clean, object-based configuration for complex setups
- Production-Ready Architecture - Event-driven design with no timeouts or polling
- Complete API Coverage - 19+ methods with consistent Promise-based returns
- Enterprise Applications - Robust, scalable PDF viewing for business applications
- Document Management Systems - Complete PDF handling with search and navigation
- E-Learning Platforms - Interactive PDF viewing for educational content
- Financial Applications - Secure PDF viewing for reports and statements
- Healthcare Systems - Reliable PDF viewing for medical documents
- Government Portals - Accessible PDF viewing for public services
- E-Commerce Platforms - Product catalogs and documentation viewing
- Content Management Systems - Integrated PDF viewing and management
- Quick Start
- Features
- Installation
- Basic Usage
- Advanced Configuration
- API Reference
- Examples
- Migration Guide
- Deprecated Features
- Contributing
- License
π― Live Demo: https://angular-pdf-viewer-demo.vercel.app/
π Source Code: https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp
npm install ng2-pdfjs-viewer --save
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { PdfJsViewerModule } from "ng2-pdfjs-viewer";
@NgModule({
imports: [BrowserModule, PdfJsViewerModule],
// ... rest of your module
})
export class AppModule {}
<ng2-pdfjs-viewer
pdfSrc="assets/sample.pdf"
[showSpinner]="true"
[theme]="'light'"
>
</ng2-pdfjs-viewer>
Add PDF.js assets to your angular.json
:
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"assets": [
{
"glob": "**/*",
"input": "node_modules/ng2-pdfjs-viewer/pdfjs",
"output": "/assets/pdfjs"
}
]
}
}
}
}
}
}
π 7+ Million Downloads & Counting! - Trusted by developers worldwide for reliable PDF viewing in Angular applications since 2018.
- π High-Quality PDF Rendering - Powered by Mozilla's PDF.js v5.3.93 for superior document display
- π Multiple Display Modes - Embedded viewer, new window, or external tab options
- π± Mobile-First Responsive Design - Touch-friendly controls optimized for all devices
- π Complete Internationalization - Support for 50+ languages with automatic locale detection
- β‘ Optimized Performance - Lazy loading, memory management, and efficient rendering
- π¨ Theme System - Light, dark, and auto themes with custom color schemes
- π Custom Styling - CSS custom properties for complete visual control
- π Loading States - Custom loading spinners with template support
- β Error Handling - Multiple error display styles with custom templates
- π Layout Control - Toolbar density, sidebar width, and positioning options
- π TypeScript Support - Full type safety with strict mode
- π Event System - Comprehensive event handling for all user interactions
- βοΈ Configuration Objects - Convenience setters for cleaner code
- π οΈ API Methods - Promise-based methods for programmatic control
- π Debugging - Built-in diagnostic logging and error tracking
- π Search & Navigation - Full-text search with highlighting
- π Bookmarks & Attachments - Document structure navigation
- π¨οΈ Print & Download - Built-in print and download functionality
- π Rotation & Zoom - Document manipulation with smooth animations
- π± Touch Gestures - Mobile-optimized touch interactions
- Angular: 20.0+ (recommended) | 2.0+ (supported)
- Node.js: 18.0+
- TypeScript: 5.0+
Angular Version | Support Level | Notes |
---|---|---|
20.0+ | β Recommended | Fully tested and optimized |
15.0 - 19.x | β Supported | Should work with minor testing |
10.0 - 14.x | β Supported | Compatible with testing |
2.0 - 9.x | May require additional testing |
Note: While the library supports Angular 2.0+, it's primarily tested and optimized for Angular 20+. For production use with older versions, thorough testing is recommended. The library uses relaxed peer dependencies (Angular >=10.0.0) to ensure compatibility across different Angular versions.
# Using npm
npm install ng2-pdfjs-viewer --save
# Using yarn
yarn add ng2-pdfjs-viewer
# Using pnpm
pnpm add ng2-pdfjs-viewer
Add PDF.js assets to your angular.json
:
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"assets": [
{
"glob": "**/*",
"input": "node_modules/ng2-pdfjs-viewer/pdfjs",
"output": "/assets/pdfjs"
}
]
}
}
}
}
}
}
<ng2-pdfjs-viewer pdfSrc="assets/document.pdf" [showSpinner]="true">
</ng2-pdfjs-viewer>
<ng2-pdfjs-viewer
pdfSrc="assets/document.pdf"
[theme]="'dark'"
[primaryColor]="'#007acc'"
[showSpinner]="true"
[customSpinnerTpl]="customSpinner"
[customErrorTpl]="customError"
(onDocumentLoad)="onDocumentLoaded($event)"
(onPageChange)="onPageChanged($event)"
>
</ng2-pdfjs-viewer>
import { Component, ViewChild } from "@angular/core";
import { PdfJsViewerComponent } from "ng2-pdfjs-viewer";
@Component({
template: `
<ng2-pdfjs-viewer #pdfViewer pdfSrc="document.pdf"></ng2-pdfjs-viewer>
<button (click)="goToPage(5)">Go to Page 5</button>
`,
})
export class MyComponent {
@ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
async goToPage(page: number) {
await this.pdfViewer.goToPage(page);
}
}
// Component
export class MyComponent {
themeConfig = {
theme: "light",
primaryColor: "#007acc",
backgroundColor: "#ffffff",
toolbarColor: "#f5f5f5",
textColor: "#333333",
borderRadius: "8px",
};
}
<!-- Template -->
<ng2-pdfjs-viewer [themeConfig]="themeConfig" [customCSS]="customStyles">
</ng2-pdfjs-viewer>
<ng-template #customSpinner>
<div class="custom-spinner">
<div class="spinner"></div>
<p>Loading PDF...</p>
</div>
</ng-template>
<ng2-pdfjs-viewer
[customSpinnerTpl]="customSpinner"
[spinnerClass]="'my-spinner'"
>
</ng2-pdfjs-viewer>
<ng-template #customError>
<div class="error-container">
<mat-icon>error</mat-icon>
<h3>Failed to Load PDF</h3>
<p>Please check your internet connection and try again.</p>
<button mat-button (click)="retry()">Retry</button>
</div>
</ng-template>
<ng2-pdfjs-viewer [customErrorTpl]="customError" [errorClass]="'my-error'">
</ng2-pdfjs-viewer>
Property | Type | Default | Description |
---|---|---|---|
pdfSrc |
string | Blob | Uint8Array |
- | PDF source (URL, Blob, or byte array) |
viewerId |
string |
auto | Unique viewer identifier |
viewerFolder |
string |
'assets' |
Path to PDF.js assets |
externalWindow |
boolean |
false |
Open in new window |
externalWindowOptions |
string |
- | External window options |
target |
string |
'_blank' |
Target for external window |
theme |
'light' | 'dark' | 'auto' |
'light' |
Theme selection |
primaryColor |
string |
'#007acc' |
Primary color for UI elements |
backgroundColor |
string |
'#ffffff' |
Background color |
pageBorderColor |
string |
- | Page border color |
toolbarColor |
string |
- | Toolbar background color |
textColor |
string |
- | Text color |
borderRadius |
string |
- | Border radius |
customCSS |
string |
- | Custom CSS styles |
showSpinner |
boolean |
true |
Show loading spinner |
customSpinnerTpl |
TemplateRef |
- | Custom spinner template |
spinnerClass |
string |
- | Custom spinner CSS class |
customErrorTpl |
TemplateRef |
- | Custom error template |
errorClass |
string |
- | Custom error CSS class |
errorOverride |
boolean |
false |
Override default error handling |
errorAppend |
boolean |
true |
Append to default error messages |
errorMessage |
string |
- | Custom error message |
locale |
string |
'en-US' |
UI language |
useOnlyCssZoom |
boolean |
false |
Use CSS-based zoom for mobile |
diagnosticLogs |
boolean |
false |
Enable diagnostic logging |
zoom |
string |
'auto' |
Initial zoom level (two-way binding) |
page |
number |
1 |
Initial page number |
namedDest |
string |
- | Named destination to navigate to |
cursor |
string |
'select' |
Cursor type (two-way binding) |
scroll |
string |
'vertical' |
Scroll mode (two-way binding) |
spread |
string |
'none' |
Spread mode (two-way binding) |
pageMode |
string |
'none' |
Page mode (two-way binding) |
rotation |
number |
0 |
Document rotation (two-way binding) |
showOpenFile |
boolean |
true |
Show open file button |
showDownload |
boolean |
true |
Show download button |
showPrint |
boolean |
true |
Show print button |
showFind |
boolean |
true |
Show search button |
showFullScreen |
boolean |
true |
Show fullscreen button |
showViewBookmark |
boolean |
true |
Show bookmark button |
showAnnotations |
boolean |
false |
Show annotations |
showToolbarLeft |
boolean |
true |
Show left toolbar section |
showToolbarMiddle |
boolean |
true |
Show middle toolbar section |
showToolbarRight |
boolean |
true |
Show right toolbar section |
showSecondaryToolbarToggle |
boolean |
true |
Show secondary toolbar toggle |
showSidebar |
boolean |
true |
Show sidebar |
showSidebarLeft |
boolean |
true |
Show left sidebar |
showSidebarRight |
boolean |
true |
Show right sidebar |
toolbarDensity |
'compact' | 'default' | 'comfortable' |
'default' |
Toolbar density |
sidebarWidth |
string |
- | Sidebar width (e.g., '280px') |
toolbarPosition |
'top' | 'bottom' |
'top' |
Toolbar position |
sidebarPosition |
'left' | 'right' |
'left' |
Sidebar position |
responsiveBreakpoint |
string | number |
- | Responsive breakpoint |
downloadOnLoad |
boolean |
false |
Auto-download on load |
printOnLoad |
boolean |
false |
Auto-print on load |
rotateCW |
boolean |
false |
Rotate clockwise on load |
rotateCCW |
boolean |
false |
Rotate counter-clockwise on load |
showLastPageOnLoad |
boolean |
false |
Go to last page on load |
downloadFileName |
string |
- | Custom download filename |
controlVisibility |
ControlVisibilityConfig |
- | Control visibility configuration |
autoActions |
AutoActionConfig |
- | Auto actions configuration |
errorHandling |
ErrorConfig |
- | Error handling configuration |
viewerConfig |
ViewerConfig |
- | Viewer configuration |
themeConfig |
ThemeConfig |
- | Theme configuration |
groupVisibility |
GroupVisibilityConfig |
- | Group visibility configuration |
layoutConfig |
LayoutConfig |
- | Layout configuration |
Event | Type | Description |
---|---|---|
onDocumentLoad |
EventEmitter<void> |
Fired when document loads |
onDocumentInit |
EventEmitter<void> |
Fired when document initializes |
onDocumentError |
EventEmitter<DocumentError> |
Fired when document fails to load |
onPageChange |
EventEmitter<ChangedPage> |
Fired when page changes |
onPagesInit |
EventEmitter<PagesInfo> |
Fired when pages are initialized |
onPageRendered |
EventEmitter<PageRenderInfo> |
Fired when a page is rendered |
onScaleChange |
EventEmitter<ChangedScale> |
Fired when zoom/scale changes |
onRotationChange |
EventEmitter<ChangedRotation> |
Fired when rotation changes |
onPresentationModeChanged |
EventEmitter<PresentationMode> |
Fired when presentation mode changes |
onOpenFile |
EventEmitter<void> |
Fired when open file is clicked |
onFind |
EventEmitter<FindOperation> |
Fired when search is performed |
onUpdateFindMatchesCount |
EventEmitter<FindMatchesCount> |
Fired when search matches are updated |
onMetadataLoaded |
EventEmitter<DocumentMetadata> |
Fired when document metadata loads |
onOutlineLoaded |
EventEmitter<DocumentOutline> |
Fired when document outline loads |
onAnnotationLayerRendered |
EventEmitter<AnnotationLayerRenderEvent> |
Fired when annotation layer renders |
onBookmarkClick |
EventEmitter<BookmarkClick> |
Fired when bookmark is clicked |
onIdle |
EventEmitter<void> |
Fired when viewer becomes idle |
onBeforePrint |
EventEmitter<void> |
Fired before printing |
onAfterPrint |
EventEmitter<void> |
Fired after printing |
zoomChange |
EventEmitter<string> |
Fired when zoom changes (two-way binding) |
cursorChange |
EventEmitter<string> |
Fired when cursor changes (two-way binding) |
scrollChange |
EventEmitter<string> |
Fired when scroll changes (two-way binding) |
spreadChange |
EventEmitter<string> |
Fired when spread changes (two-way binding) |
pageModeChange |
EventEmitter<string> |
Fired when page mode changes (two-way binding) |
Method | Parameters | Returns | Description |
---|---|---|---|
refresh() |
- | void |
Refresh viewer |
goToPage(page: number) |
page: number |
Promise<ActionExecutionResult> |
Navigate to specific page |
setPage(page: number) |
page: number |
Promise<ActionExecutionResult> |
Set current page |
setZoom(zoom: string) |
zoom: string |
Promise<ActionExecutionResult> |
Set zoom level |
setCursor(cursor: string) |
cursor: 'select' | 'hand' | 'zoom' |
Promise<ActionExecutionResult> |
Set cursor type |
setScroll(scroll: string) |
scroll: 'vertical' | 'horizontal' | 'wrapped' | 'page' |
Promise<ActionExecutionResult> |
Set scroll mode |
setSpread(spread: string) |
spread: 'none' | 'odd' | 'even' |
Promise<ActionExecutionResult> |
Set spread mode |
setPageMode(mode: string) |
mode: 'none' | 'thumbs' | 'bookmarks' | 'attachments' |
Promise<ActionExecutionResult> |
Set page mode |
triggerDownload() |
- | Promise<ActionExecutionResult> |
Trigger download |
triggerPrint() |
- | Promise<ActionExecutionResult> |
Trigger print |
triggerRotation(direction: string) |
direction: 'cw' | 'ccw' |
Promise<ActionExecutionResult> |
Rotate document |
goToLastPage() |
- | Promise<ActionExecutionResult> |
Navigate to last page |
sendViewerControlMessage(action: string, payload: any) |
action: string, payload: any |
Promise<any> |
Send custom control message |
getActionStatus(actionId: string) |
actionId: string |
Promise<ActionExecutionResult | null> |
Get action status |
getQueueStatus() |
- | { queuedActions: number; executedActions: number } |
Get queue status |
clearActionQueue() |
- | void |
Clear action queue |
reloadViewer() |
- | void |
Reload viewer (alias for refresh) |
goBack() |
- | void |
Go back in browser history |
closeViewer() |
- | void |
Close viewer window |
getErrorTemplateData() |
- | any |
Get error template data |
π― Live Demo: https://angular-pdf-viewer-demo.vercel.app/
π Source Code: https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp
<ng2-pdfjs-viewer pdfSrc="assets/sample.pdf" [showSpinner]="true">
</ng2-pdfjs-viewer>
<ng2-pdfjs-viewer
pdfSrc="assets/sample.pdf"
[theme]="'dark'"
[primaryColor]="'#ff6b6b'"
[backgroundColor]="'#2c3e50'"
>
</ng2-pdfjs-viewer>
<ng-template #loadingTemplate>
<div class="loading">
<mat-spinner></mat-spinner>
<p>Loading your document...</p>
</div>
</ng-template>
<ng-template #errorTemplate>
<div class="error">
<mat-icon>error_outline</mat-icon>
<h3>Oops! Something went wrong</h3>
<p>We couldn't load your PDF. Please try again.</p>
<button mat-button (click)="retry()">Retry</button>
</div>
</ng-template>
<ng2-pdfjs-viewer
pdfSrc="assets/sample.pdf"
[customSpinnerTpl]="loadingTemplate"
[customErrorTpl]="errorTemplate"
>
</ng2-pdfjs-viewer>
export class PdfController {
// Group visibility configuration
groupVisibility = {
"download": true,
"print": true,
"find": true,
"fullScreen": true,
"openFile": true,
"viewBookmark": true,
"annotations": false
};
// Auto actions configuration
autoActions = {
"downloadOnLoad": false,
"printOnLoad": false
};
// Control visibility configuration
controlVisibility = {
"showToolbarLeft": true,
"showToolbarMiddle": true,
"showToolbarRight": true,
"showSecondaryToolbarToggle": true,
"showSidebar": true,
"showSidebarLeft": true,
"showSidebarRight": true
};
}
<ng2-pdfjs-viewer
pdfSrc="assets/sample.pdf"
[groupVisibility]="groupVisibility"
[autoActions]="autoActions"
[controlVisibility]="controlVisibility"
>
</ng2-pdfjs-viewer>
export class PdfController {
@ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
async loadDocument(url: string) {
this.pdfViewer.pdfSrc = url;
await this.pdfViewer.refresh();
}
async goToPage(page: number) {
await this.pdfViewer.goToPage(page);
}
async setZoom(zoom: string) {
await this.pdfViewer.setZoom(zoom);
}
}
For server-side developers, we provide comprehensive examples for integrating PDF APIs with ng2-pdfjs-viewer:
π Server-Side Examples - Complete examples for:
- ASP.NET Core (C#) - RDLC reports, physical files, iTextSharp
- Node.js (Express) - File serving, PDFKit, Puppeteer
- Python (FastAPI) - ReportLab, WeasyPrint, file handling
- Java (Spring Boot) - iText, JasperReports, file serving
- PHP (Laravel) - TCPDF, DomPDF, file management
- Go (Gin) - gofpdf, file serving, PDF generation
Each example includes proper Content-Type headers, error handling, CORS configuration, and Angular integration patterns.
- PDF.js Upgrade: Updated to v5.3.93 - some APIs may have changed
- Theme System: New theme properties replace old styling options
- Error Handling: Template-based error system replaces HTML strings
-
Update Dependencies
npm install ng2-pdfjs-viewer@latest
-
Update Theme Configuration
// Old way [customCSS]="'body { background: red; }'" // New way [theme]="'light'" [primaryColor]="'#ff0000'" [backgroundColor]="'#ffffff'"
-
Update Error Handling
<!-- Old way --> [errorHtml]="'<div>Custom error</div>'" <!-- New way --> <ng-template #errorTemplate> <div>Custom error</div> </ng-template> <ng2-pdfjs-viewer [customErrorTpl]="errorTemplate"></ng2-pdfjs-viewer>
-
Update Spinner Handling
<!-- Old way --> [spinnerHtml]="'<div class=\"spinner\">Loading...</div>'" <!-- New way --> <ng-template #spinnerTemplate> <div class="spinner">Loading...</div> </ng-template> <ng2-pdfjs-viewer [customSpinnerTpl]="spinnerTemplate"></ng2-pdfjs-viewer>
// Old way this.pdfViewer.setSpinnerHtml('<div>Loading...</div>'); // New way // Use [customSpinnerTpl] with ng-template
The following features are deprecated and will be removed in future versions:
Deprecated | Replacement | Description |
---|---|---|
[startDownload] |
[downloadOnLoad] |
Download document automatically when it opens |
[startPrint] |
[printOnLoad] |
Print document automatically when it opens |
[errorHtml] |
[customErrorTpl] |
Custom error HTML (use template instead) |
[errorTemplate] |
[customErrorTpl] |
Custom error template (renamed) |
[spinnerHtml] |
[customSpinnerTpl] |
Custom spinner HTML (use template instead) |
Deprecated | Replacement | Description |
---|---|---|
setErrorHtml() |
Use [customErrorTpl] |
Set custom error HTML (use template instead) |
setSpinnerHtml() |
Use [customSpinnerTpl] |
Set custom spinner HTML (use template instead) |
// Deprecated - Error Handling
this.pdfViewer.setErrorHtml("<div>Error</div>");
// New way - Error Handling
// Use [customErrorTpl] with ng-template
// Deprecated - Spinner Handling
this.pdfViewer.setSpinnerHtml("<div>Loading...</div>");
// New way - Spinner Handling
// Use [customSpinnerTpl] with ng-template
- Custom CSS Examples - Complete styling guide with theme customization examples
- Error Display Examples - Custom error template examples and styling options
- Contributing Guide - How to contribute to the project
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/intbot/ng2-pdfjs-viewer.git
# Clear Angular cache (Windows)
Remove-Item -Recurse -Force "SampleApp\.angular"
# Build and test - All at once (Windows)
@test.bat
This project is licensed under the Apache License 2.0 + Commons Clause License Condition v1.0 - see the LICENSE file for details.
- Community Contributors - For bug reports, feature requests, and contributions
- 7+ Million Users - For trusting us with your PDF viewing needs
- Mozilla PDF.js Team - For the amazing PDF.js library
- π Documentation: GitHub Wiki
- π¬ Community: GitHub Discussions
- π Issues: GitHub Issues
- π§ Email: [email protected]
- π§ Author: Aneesh Gopalakrishnan