Open-source project
stephanrauh/ngx-extended-pdf-viewer avatar
stephanrauh/ngx-extended-pdf-viewer

ngx-extended-pdf-viewer ships Mozilla pdf.js with an Angular UI around it

A full-blown PDF viewer for Angular 19, 20, and beyond

582 stars211 forksFluentApache-2.0

At a glance

What is it?
ngx-extended-pdf-viewer is an Angular component library that wraps Mozilla's pdf.js, adding a full editing and viewing interface on top of the renderer. Version 31 tracks pdf.js 6.4, and the project ships breaking changes with each major release, which is the main cost of adopting it.
Who is it for?
Adopt ngx-extended-pdf-viewer if you need a PDF viewer inside an Angular application with annotations, form handling, text selection and a maintained UI, and you are prepared to read the changelog on every major bump. Skip it if you need a bare renderer with no UI, or if your application is not Angular, since this is an Angular component library and the topic list names Angular and pdfjs only.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Fluent, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

pdf.js plus the interface Mozilla did not write

The project's own summary is short and precise: it brings Mozilla's pdf.js to the Angular world, and that is not only the core PDF viewer but also the UI. That distinction is the whole value proposition. pdf.js is a rendering library, capable but bare, and turning it into something an end user can read a document in means building a toolbar, a sidebar, a zoom control, a page view, a search box, an annotation surface and a keyboard model. ngx-extended-pdf-viewer ships all of that as an Angular component, so an application gets a working document viewer with a `<ngx-extended-pdf-viewer>` element rather than a rendering API to build on. The homepage is a demo site with live examples, source code samples and a handbook, and the topics tag the project with angular, embedding-pdf, mozilla-pdf, pdf, pdf-viewer and pdfjs. The primary language in the repository metadata is Fluent, which is the localisation format, so the component's own user interface strings are translated, and the repository carries a `merge-translations.js` script at the top level to handle that.

Version 31 and what it changed about text and forms

Version 31 ships pdf.js 6.4 in both the stable and the bleeding-edge bundle, and most of the change list is about behaviour a user would notice. Highlighting and drawing are built on Mozilla's reworked editors, a two-finger gesture pans the document while you pinch, large JPEG images need noticeably less memory, and PDF files with CMYK colours are rendered with colour management. There is an eraser for drawings and free-hand highlights, toggled with `[showEraserEditor]` and `[disableEraserEditor]`, and undo and redo buttons for the annotation editor, which the changelog notes are hidden by default after being visible in the 31.0.0 alphas, with both contributed by an outside contributor. Two breaking changes are the ones to read before upgrading. Setting `[textLayer]="false"` now genuinely turns the text layer off and hides the select tool button, where previously the layer was rendered anyway and text stayed selectable, so if you rely on text selection, highlighting of selected text or screen reader support you must remove the attribute. And `getFormData()` now reports values for fields the user has not changed, which used to be `undefined`, so code that used `value === undefined` to find untouched fields has to compare `value` with `fieldValue` instead.

Accessibility work and the older browser bundle

Two changes in version 31 are about who can use the viewer. On accessibility, screen readers now hear which editor is active and which panels and menu entries are switched on, and `[startTabindex]` numbers the buttons in the order the user sees them rather than in DOM order. On older browsers, browsers that need the legacy bundle now get the legacy worker and scripting sandbox as well, which fixed a class of failure where a modern browser path was served to a browser that could not run it. There is also an error card for documents that fail to load, switched on with `[showLoadingErrorMessage]="true"` and with `[loadingErrorMessage]` for your own headline text, contributed by another outside contributor. The overall pattern in this release is a project that is taking accessibility and failure states seriously rather than treating them as an afterthought, and the fact that both the eraser feature and the loading error card came from outside contributors says the extension points are open.

Book mode and the reading direction change in 31

Book mode turns right-to-left books from left to right, opens at the `[page]` attribute instead of on the cover, and keeps both pages side by side when you zoom in. Past the page size it activates the hand tool, so a drag moves the page rather than turning it. The related breaking change is that book mode now follows the reading direction: when the UI language is Arabic, Hebrew, Persian or Urdu, books open on the left and turn their pages from left to right, and `[readingDirection]="ltr"` restores the old behaviour. There is a second, separate change in the same release that is arguably more important for anyone embedding the viewer. The document properties dialog now looks like the comment dialog, with new markup and button classes, and the `$document-properties-*` SCSS variables are gone. Dialog buttons carry the classes `primaryButton` or `secondaryButton`, the checkmark of a menu is mirrored with a `transform`, and the view switcher uses logical paddings and margins. If you themed the viewer with those SCSS variables, that is work waiting for you.

Version 30 stopped the viewer writing to your html element

The previous major release fixed a class of bug that is worth understanding because it shows the coupling between the viewer and the host page. Until version 30, the viewer wrote to your application's `<html>` tag: the reading direction of the UI language, so an Arabic PDF flipped your entire application to right-to-left and left it that way after the viewer was destroyed, plus its layout variables `--viewer-container-height`, `--viewsManager-width` and `color-scheme`. All of that now goes to the viewer's own `.html` and `.body` elements, which wrap the viewer inside your page. The breaking change only bites if you style the viewer from the outside or replace its template. CSS overrides keyed on `<html>`, such as `html[dir='rtl'] ngx-extended-pdf-viewer .toolbarButton`, no longer match, and the new selector is `ngx-extended-pdf-viewer .body[dir='rtl'] .toolbarButton`. Code that reads the layout variables from `document.documentElement` now gets nothing. And if you pass your own template via `[customPdfViewer]`, you have to keep the `.html` and `.body` wrapper elements around `#outerContainer`, because the viewer uses them to scope its styles.

Using it: the npm package, the CDN and the documented setup

The distribution channels are ordinary for an Angular library. The package is published to npm as `ngx-extended-pdf-viewer`, and the README carries a CDN pointer to unpkg.com for the same package. The project describes itself as a PDF viewer for Angular 19, 20 and beyond, and the setup instructions and live demos live on the demo site rather than in the repository README, which tells you that if something does not work there is a troubleshooting page on the same site. The repository itself is a monorepo-style workspace with the library under `projects/`, an `src/` directory, a `build-tools/` directory of numbered build scripts, `compatibility-tests/`, and a `ftp/` directory. The package manifest in the repository is for the demo application, and its script names explain the pipeline: a base library build, a pdf.js provenance update, SBOM generation and validation, then the library, the demo site, and combinations of the two with old and new demo site variants.

json
    "build:base": "node ./build-tools/1-build-base-library.js",
    "build:provenance": "node ./build-tools/base-library/update-pdfjs-provenance.js",
    "build:sbom": "node ./build-tools/generate-sbom.js",
    "build:lib": "node ./build-tools/2-build-library.js",

The security posture in the build scripts is worth noticing too. The install script runs with `--ignore-scripts` throughout and then runs a search script named for the Shai-Hulud npm supply chain attack, and a `preinstall` hook runs a check-ignore-scripts script of its own. The repository also has a `SECURITY.md`, a `NOTICE` file, dependabot configuration and a `.whitesource` directory, which is a reasonable set of signals for a library that is embedded in other people's applications.

Release cadence and the cost of tracking pdf.js closely

The releases are frequent and the version numbers are large. The listed ones are 31.0.0-rc.0 on 2026-10-08, 31.0.0 on 2026-10-10 and 31.0.1 on 2026-10-17, with the last push on 2026-10-19. So this is a project shipping majors weekly-ish, and the majors carry breaking changes, which is the central adoption cost. The cause is the coupling to Mozilla. Each new pdf.js version brings new capability and, sometimes, changed behaviour that the Angular layer has to expose differently, and the maintainer is explicit about it: version 30 ships pdf.js 6.2, version 31 ships pdf.js 6.4, and both ship in the stable and bleeding-edge bundle. The upside of that coupling is that you are not waiting for a wrapper to catch up with an upstream renderer. The downside is that a version bump of the library can change the semantics of existing attributes, as `[textLayer]="false"` did, or move CSS variables, as the `$document-properties-*` SCSS variables did. The repository's own `TODO-next-major-version.md` file is a hint about where the maintainer thinks the next breaking release will land.

Editorial conclusion

Adopt ngx-extended-pdf-viewer if you need a PDF viewer inside an Angular application with annotations, form handling, text selection and a maintained UI, and you are prepared to read the changelog on every major bump. Skip it if you need a bare renderer with no UI, or if your application is not Angular, since this is an Angular component library and the topic list names Angular and pdfjs only. Before you commit, check the pdf.js version your release carries, because the library tracks Mozilla upstream closely and the breaking changes in version 30 and 31 came from that coupling.

Frequently asked questions

What does ngx-extended-pdf-viewer add on top of pdf.js?

It brings pdf.js to Angular and adds the UI around it, not only the renderer. The project describes itself as a full-blown PDF viewer for Angular 19, 20 and beyond, and the repository's primary language is Fluent, which is the localisation format for the component's own interface strings.

Which pdf.js version does ngx-extended-pdf-viewer 31 use?

Version 31 ships pdf.js 6.4 in both the stable and the bleeding-edge bundle. Version 30 shipped pdf.js 6.2, so the library tracks Mozilla upstream closely and the major versions arrive frequently.

What breaking changes did version 31 of ngx-extended-pdf-viewer bring?

Setting `[textLayer]="false"` now really turns the text layer off and hides the select tool button, where text was previously still selectable, and `getFormData()` now reports unchanged form field values that used to be `undefined`. The `$document-properties-*` SCSS variables are also gone.

How do I style the ngx-extended-pdf-viewer from outside the component?

Since version 30 the viewer writes to its own `.html` and `.body` wrapper elements rather than your application's `<html>` tag, so an override like `html[dir='rtl'] ngx-extended-pdf-viewer .toolbarButton` no longer matches and `ngx-extended-pdf-viewer .body[dir='rtl'] .toolbarButton` should be used instead. If you supply your own template via `[customPdfViewer]`, keep the `.html` and `.body` elements around `#outerContainer`.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. stephanrauh/ngx-extended-pdf-viewer on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stephanrauh-ngx-extended-pdf-viewer.svg)](https://hysenlabs.com/projects/stephanrauh-ngx-extended-pdf-viewer)

Was this useful?