
Research
Malicious fezbox npm Package Steals Browser Passwords from Cookies via Innovative QR Code Steganographic Technique
A malicious package uses a QR code as steganography in an innovative technique.
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 |
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.
# 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 |
<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 {
@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);
}
}
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>
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
this.pdfViewer.setErrorHtml("<div>Error</div>");
// New way
// Use [customErrorTpl] 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
# Install dependencies
npm install
# 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
The most comprehensive Angular PDF viewer powered by Mozilla PDF.js. 7M+ downloads, mobile-first, production-ready with complete rewrite in v25.x
The npm package ng2-pdfjs-viewer receives a total of 26,841 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.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.
Application Security
/Research
/Security News
Socket detected multiple compromised CrowdStrike npm packages, continuing the "Shai-Hulud" supply chain attack that has now impacted nearly 500 packages.