PDF viewer
A read-only PDF viewer over Mozilla's pdf.js: pages drawn as they come near the viewport, page thumbnails, find in document with highlights, zoom by steps or to the width or the page, and printing. pdf.js renders the pages; the viewer adds the chrome, keyboard, text layer for selection and screen readers, and the theme-aware toolbar of the other document viewers.
pdfjs-dist is an optional peer dependency loaded on first use, so an application that never shows a PDF never downloads it. Serve its worker (pdf.worker.min.mjs) and name it with provideOgePdfViewerConfig({ workerSrc }). Fonts are never evaluated as code and scripts and form actions never run. Covered by the same license as the other document viewers.
Getting started
Point source at a PDF. Page Up, Page Down, Home and End move between pages, Ctrl + / − / 0 zoom, and Enter / Shift+Enter in the find box step through the matches.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { OgePdfViewer, provideOgePdfViewerConfig } from '@oge-ui/spreadsheet/pdf';
@Component({
selector: 'demo-root',
imports: [OgePdfViewer],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- pdf.js loads on first use. The toolbar pages, zooms, fits, finds
and prints; pages are drawn only when they come near the viewport. -->
<oge-pdf-viewer source="/demo/spreadsheet/report.pdf" style="height: 640px" />
`,
})
export class Demo {}
// npm i pdfjs-dist, and serve node_modules/pdfjs-dist/build/pdf.worker.min.mjs
// (angular.json assets: { glob: "pdf.worker.min.mjs", input: "node_modules/pdfjs-dist/build", output: "pdfjs" })
export const appConfig = {
providers: [provideOgePdfViewerConfig({ workerSrc: '/pdfjs/pdf.worker.min.mjs' })],
};Controlled view
[(pageIndex)], [(zoom)] and [(showThumbnails)] keep the view in your own state: they follow the toolbar and the scrolling, and move the viewer when you set them.
Page 1 · zoom 1
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { OgePdfViewer } from '@oge-ui/spreadsheet/pdf';
import type { OgePdfZoom } from '@oge-ui/spreadsheet/pdf';
@Component({
selector: 'demo-root',
imports: [OgePdfViewer],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- page, zoom and the thumbnail sidebar are two-way: they follow the
toolbar and the scrolling, and move the viewer when you set them. -->
<p>Page {{ page() + 1 }} · zoom {{ zoom() }}</p>
<oge-pdf-viewer
source="/demo/spreadsheet/report.pdf"
[(pageIndex)]="page"
[(zoom)]="zoom"
[(showThumbnails)]="thumbs"
style="height: 520px"
/>
`,
})
export class Demo {
readonly page = signal(0);
readonly zoom = signal<OgePdfZoom>(1);
readonly thumbs = signal(true);
}Bare preview
[toolbar]="false" leaves just the pages, for a preview pane; source takes a File the user picked, read in the browser.
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { OgePdfViewer } from '@oge-ui/spreadsheet/pdf';
@Component({
selector: 'demo-root',
imports: [OgePdfViewer],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- [toolbar]="false" leaves just the pages, for a preview pane; source
takes a File the user picked, read in the browser. -->
<input
type="file"
accept="application/pdf"
aria-label="Choose a PDF"
(change)="pick($event)"
/>
<oge-pdf-viewer
[source]="file() ?? '/demo/spreadsheet/report.pdf'"
[toolbar]="false"
zoom="fit-page"
style="height: 420px"
/>
`,
})
export class Demo {
readonly file = signal<File | null>(null);
pick(event: Event): void {
this.file.set((event.target as HTMLInputElement).files?.[0] ?? null);
}
}