
Product
Rust Support Now in Beta
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
ng2-pdfjs-viewer
Advanced tools
The most reliable, feature-rich Angular PDF viewer component powered by Mozilla's PDF.js
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.
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 |
🎯 Live Demo: https://angular-pdf-viewer-demo.vercel.app/
📚 Documentation: https://angular-pdf-viewer-docs.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.
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 | ⚠️ Legacy | 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/
📚 Documentation: https://angular-pdf-viewer-docs.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:
Each example includes proper Content-Type headers, error handling, CORS configuration, and Angular integration patterns.
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
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.
FAQs
README.md
The npm package ng2-pdfjs-viewer receives a total of 27,084 weekly downloads. As such, ng2-pdfjs-viewer popularity was classified as popular.
We found that ng2-pdfjs-viewer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.