- 10 minutes read

There are two popular libraries to embed a PDF file in your Angular application. Actually, when you're googling, you'll find three solutions. However, I reckon you're not interested in good old AngularJS 1.x. Plus, there's the option you won't find easily on Google (yet). That's my pet library. It had grown surprisingly popular on npm even before I started any marketing effort, but even so, it has yet to make an impact on the Google search index.

Let's have a look at these four options. Why are there three[1] different options to embed PDF in your application? What are the pros and cons? When and why should you choose my library?

Using the built-in PDF viewer of your browser

In a way, it's crazy to use a library to display PDF files in a browser. Every modern browser can show PDF files natively. Just drag and drop a PDF file into the browser, and you'll see a PDF viewer that's every bit as powerful as Adobe's native PDF viewer.

Only - well, there are some outdated versions of our good old friend called Internet Explorer out there. Plus, many other browsers don't support PDF files. Sometimes it's not enough to focus on the evergreen browsers. Adding insult to injury, there's no standardized way to embed a PDF file on a web page, and the public API is limited. What you can do is using the <object> tag like so:

Your browser does not support PDFs. Download the PDF

Philipp Spiess has an exhaustive roundup of this approach. Highly recommended. Be warned: Along the way, he's trying to sell you a professional PDF tool which may or may not be useful. I wouldn't know because BeyondJava.net is very serious about never doing advertising. So I didn't even evaluate it.

The PDF viewer of Mozilla and Chrome

Both Firefox and Chrome use an open-source PDF viewer called pdf.js. It's written in JavaScript, so it's easy to use the library in your own project.

Several tutorials are telling you how easy it is to use pdf.js. For example, the author I've already quoted, Philipp Spiess, has written a nice walkthrough.

The catch is it's easy as long as you're happy with just displaying the PDF file without any bells and whistles. As soon as you want to add more features - such as scaling, searching, rotating, printing - complexity quickly gets through the roof. Most tutorials solve the problem by embedding Mozilla's web viewer in an iFrame. The good news is that this approach works. Nonetheless, in many projects, that's a no-go. iFrames went out of fashion for a reason.

What we're looking for is a simple but powerful solution.

Angular.js 1.x

The first result of a Google search is a library looking like the perfect solution. There are just two disadvantages: it's an AngularJS library, and the authors ceased to maintain it. Still, if you happen to work on an AngularJS 1.x project, angular-pdfjs-viewer is a fine library.

ng2-pdf-viewer: Displaying PDF files in a no-nonsense way

This library is the way to go if you just want to render PDF files. ngx-pdf-viewer gives you a decent API, is actively maintained, and is popular enough to feel trustworthy. At the time of writing, it saw more than ten thousand downloads a week. Without having used the library myself, I suppose Vadym Yatsyuk is doing a great job with his library.

ngx-extended-pdf-viewer: the full-blown Angular 7+ solution

Things get more difficult if you need the real thing. The online demo shows what's in store for you: thumbnails, searching, printing, various selection tools, and so on. However, the online demo has not been written with embedding in mind, so it's tough to use the HTML code in your Angular application. So I've written and published my own library, ngx-extended-pdf-viewer.

Just a word of caution: as I mentioned above, this is my library. It was a lot of work, and I'm happy it works so well now. In other words: I'm proud of my library. I can't help but speak in high terms of it. So take everything I say with a grain of salt. On the plus side, I've developed the library for a professional project, and my customer is using it on a daily basis in production. So maybe it is something to be proud of indeed. :)

How to use <ngx-extended-pdf-viewer>

Getting started requires several non-standard steps. That's because the <ngx-extended-pdf-viewer> ships with HTML code, CSS, images, and translations for several dozen languages. As it turns out, Angular Elements is a great tool to publish a library to npm, but it's ill-prepared to put resource files into the library. I plan to publish the library as a framework-agnostic WebComponent soon. Until then, you need to add two sections of the angular.json. But fear not: the project page on npm has a detailed walk-through. It's easy!

Apart from tweaking the angular.json, it's the usual procedure: run an npm install ngx-extended-pdf-viewer --save, add the NgxExtendedPdfViewerModule to the imports section of your module file, and embed the viewer tag like so:

Internationalization

That's a topic I spent a considerable amount of time on. Mozilla's library ships with more than 100 language files. So supporting international users (like me) was high on my list of priorities.

Basically, ngx-extended-pdf-viewer offers two ways to translate the texts to your user's language. First, you can add a single language file to a global file such as the index.html. That approach is tremendously fast, but of course, it doesn't support more than one language. That's enough in most projects. If you need to go international, you can configure the library to load the language file from the asset folder. That's a second request, so it comes with a small performance penalty.

Customization

Not everybody needs the full range of features. For instance, the project I'm currently working on doesn't need bookmarks. ngx-extended-pdf-viewer has an option to deactivate every button of the UI.

Truth to tell, this was quite a challenge in some cases. Consider thumbnails, for example. Hiding them resulted in nasty exceptions. So I went to the pain to fix the base library. This, in turn, makes updating to new versions of pdf.js a bit cumbersome. Have a look a the How to build cheat-sheet file to get an idea of what I'm speaking about. It's a long list of steps I have to follow each time Mozilla publishes a new version of their library. On the other hand: better me than you!

Viewing PDF files with gloves

That's not a joke. ngx-extended-pdf-viewer has been optimized with gloves in mind. It's used in a manufacturing plant. The workers wear gloves to protect their fingers. Nonetheless, they are keen to use modern technology, such as touchscreens. Touch always means you have to increase the "touch area." Gloves require an even larger touch area. So you can zoom the toolbar of ngx-extended-pdf-viewer. In our case, zooming it to 150% turned out to be a good compromise.

Maturity

There's no such thing as a bug-free software - unless it's so simple it wasn't worth to write in the first place. That said, I'm positive ngx-extended-pdf-viewer is ready for production. At the time of writing, npm reports up to 600 times a week, and it receives a surprising number of issues on GitHub. These issues clearly show many developers are using the library.

Still, there are pain points. Several developers left bug reports showing they didn't get how to use the library. Obviously, I have to improve the documentation. More worrying is the memory leak of ngx-extended-pdf-viewer. Each time you close an instance of ngx-extended-pdf-viewer and open a new one, you lose roughly 30 KB of precious memory. That's an issue I'm pursuing, but it's a difficult one. The architecture of pdf.js itself causes it, so it's hard to find a non-invasive bug fix.

Oh, and there's our good old friend Internet Explorer. I've managed to make it play well with ngx-extended-pdf-viewer, but there are still a couple of rough edges, such as maintaining a persistent zoom setting resulting in an exception.

But it ain't even a 1.0 version!

At the time of writing, the current version is a 0.9.13. That's just an infinite bit away from the great 1.0.0 version. I'm reluctant to push thing because I want the 1.0.0 to be, well, glorious, so I wait for bug reports coming in. Judging by the nature of the last few bug reports, I believe I've already reached this goal, apart from the Internet Explorer bit. Chances are I'll make it a 1.0.0 early in January when most developers living in the northern hemisphere return from the winter holidays.

What about the future roadmap?

I'm not sure we're already there - but there's this wonderful thing called WebComponents or Angular Elements. If everything works out nicely, I plan to wrap <ngx-extended-pdf-viewer> in a WebComponent you can use everywhere. In your React.js project, your Vue.js project, your.Net project, your WordPress blog, and even in your BootsFaces application. Does this sound interesting? Please give me feedback, so I know how much priority I should assign to this idea.

Feedback

Talking about feedback: Like always, I appreciate your feedback. At the time of writing, I've still deactivated the comment function because of the uncertainty caused by GDPR. However, you can always report a bug at the project bug tracker, you can reach out to me by email (see the "Impressum" page of this blog), and you can tweet me (@beyondjava). I'll listen to all three channels. If there's something to improve - and I'm sure there's a lot to improve! - just tell me. I'll do it as long as my precious leisure time, and the limitations of pdf.js itself allow.

Wrapping it up

What started as a spin-off of a commercial project has evolved into a surprisingly popular open-source project. Even before I told anybody about the project, npm reported one hundred downloads per week, give or take a few. Tweeting about the project, plus publishing a dozen new preview versions, pushed the figure to more than 600 tops. By the look of it, I've hit a nerve. That's great. It's a lot of fun to work on something other developers benefit from!


  1. not counting the AngularJS library↩

Comments