This post will show you how to add a simple PDF viewer to your AngularJS app with PDF.js and the angularjs-pdf directive. We'll also show you how to match your app's look-and-feel by wrapping it in a custom UI. Like this:

AngularJS PDF.js PDF viewer

This viewer is ideal for basic viewing use cases, and includes a few basic widgets:

  • Opening a local file
  • Rotating left
  • Zooming in/out
  • Previous/next page navigation

The source code for this project is available in our Git repo. We're using PDF.js version 1.6.414.

Step 1 - Clone the Repo

Once you've created the directory where you want this app to live, clone the repo from the command line:

# command line
git clone https://github.com/PDFTron/angular-pdf-ui.git
cd angular-pdf-ui
fullscreen
Copy

To change the PDF that's loaded by default, replace PDFTron SDK and pdftron-sdk.pdf in docCtrl.js:

JavaScript
// file: angular-pdf-ui/src/js/controllers $scope.pdfName = 'PDFTron SDK'; $scope.pdfUrl = 'pdf/pdftron-sdk.pdf';
fullscreen
Copy

You can now run this basic viewer in your app. Next, we'll customize the UI...

Step 2 - Configuration

The viewer has limited options that can be configured in index.html:

<! -- file: angular-pdf-ui/src/index.html -- >
<ng-pdf
  template-url="partials/viewer.html"
  scale="page-fit"
  page="1"
  usecredentials="false"
  debug="false"
></ng-pdf>
fullscreen
Copy

The scale value can be page-fit or a number, the page value indicates the first page displayed in the viewer, while a usecredentials value of true would require a password to open the file (but it does not encrypt the file). See the official README.

The $scope.onProgress and $scope.onLoad functions can be used to show an animation while the file is loaded, and then do something when it's finished.

Step 3 - Removing Widgets From The UI

The code for displaying widgets is located in viewer.html, with widgets wrapped in <span> tags. To remove (or re-order) the widgets, simply find the tag and adjust as needed.

<! -- file: angular-pdf-ui/src/partials/viewer.html -- >
<input
  onchange="angular.element(this).scope().onFileSelected(this)"
  type="file"
  id="file"
  class="d-none"
  accept=".pdf"
/>
<div class="toolbar d-flex">
  <span
    class="my-icon"
    ng-include="'icon/baseline-open_in_browser-24px.svg'"
    ng-click="openLocalFile()"
    title="Open File"
  ></span>
  <span
    class="my-icon"
    ng-include="'icon/baseline-rotate_right-24px.svg'"
    ng-click="rotate()"
    title="Rotate Right"
  ></span>
  <span
    class="my-icon"
    ng-include="'icon/baseline-zoom_in-24px.svg'"
    ng-click="zoomIn()"
    title="Zoom In"
  ></span>
  <span
    class="my-icon"
    ng-include="'icon/baseline-zoom_out-24px.svg'"
    ng-click="zoomOut()"
    title="Zoom Out"
  ></span>

  <span
    class="my-icon ml-auto"
    ng-include="'icon/baseline-navigate_before-24px.svg'"
    ng-click="goPrevious()"
    title="Previous Page"
  ></span>
  <div>
    <input type="number" class="page-num" min="1" ng-model="pageNum" />
    <span>/ {{ pageCount }}</span>
  </div>
  <span
    class="my-icon"
    ng-include="'icon/baseline-navigate_next-24px.svg'"
    ng-click="goNext()"
    title="Next Page"
  ></span>
</div>
fullscreen
Copy

For example, delete this code to remove the rotation toggle:

<! -- file: angular-pdf-ui/src/partials/viewer.html -- >
  <span
    class="my-icon"
    ng-include="'icon/baseline-rotate_right-24px.svg'"
    ng-click="rotate()"
    title="Rotate Right"
  ></span>
fullscreen
Copy

Step 4 - Replacing Widget Icons

Widget icons are referenced individually from viewer.html, so it's easy to swap them out with whatever image you'd like to use:

<! -- file: angular-pdf-ui/src/partials/viewer.html -- >
  <span
    class="my-icon"
    ng-include="'icon/baseline-open_in_browser-24px.svg'"
    ng-click="openLocalFile()"
    title="Open File"
  ></span>
fullscreen
Copy

The above code is for the File Open widget. To use a different image, replace icon/baseline-open_in_browser-24px.svg with the one you'd like to use.

Step 5 - Changing Widget or Toolbar Styling

Widgets and the toolbar can be styled in style.css. Here we can adjust the background of the toolbar, widget sizing or padding, and more.

CSS
/* file: angular-pdf-ui/src/style.css */ *{box-sizing: border-box;} .wrapper {margin: 0 auto; width: 960px; } .pdf-controls { width: 100%; display: block; background: #eee; padding: 1em;} .rotate0 {-webkit-transform: rotate(0deg); transform: rotate(0deg); } .rotate90 {-webkit-transform: rotate(90deg); transform: rotate(90deg); } .rotate180 {-webkit-transform: rotate(180deg); transform: rotate(180deg); } .rotate270 {-webkit-transform: rotate(270deg); transform: rotate(270deg); } .fixed { position: fixed; top: 0; left: calc(50% - 480px); z-index: 100; width: 100%; padding: 1em; background: rgba(238, 238, 238,.9); width: 960px; } .toolbar { background: #303030; padding: 10px; position: fixed; left: 0; right: 0; top: 0; z-index: 9999; } .toolbar span { color: white; } .my-icon { margin: 0 7px; cursor: pointer; } .my-icon:hover { opacity: 0.5; } .my-icon.active { opacity: 0.5; } .my-icon.active:hover { opacity: 1; } .page-num { width: 50px; border: 0; margin-right: 2px; text-align: center; } .searchbox { width: 0; opacity: 0; transition: all 0.3s ease-out; border: 0px; padding: 0 3px; } .searchbox:focus, .searchbox:active { outline: 0; box-shadow: none; } .searchbox:focus { opacity: 1; width: 200px; } .pdf-body { margin-top: 46px; } input:focus, input:active { outline: 0; box-shadow: none; }
fullscreen
Copy

And that's it! You now have a simple AngularJS PDF viewer that matches your app's look-and-feel.

This is a great solution if you just need basic viewing capabilities, and you're not too concerned with PDF.js rendering inconsistencies or failures that can occur (especially the older versions). If you are in the process of evaluating PDF.js be sure to see our guide to evaluating PDF.js.

If you need to add more robust functionality, like annotation, form filling, 100% rendering reliability, and more to your viewer, we offers a JavaScript-based PDF viewer:

To see it in action check out our WebViewer demo.

Also, it's easy to integrate into your AngularJS project...

Integrating PDFTron WebViewer Into AngularJS Projects

Make sure you have Node.js installed to run the sample.

Node.js is not required for WebViewer
WebViewer does not require Node, npm, or node_modules. It is only recommended to run the samples.

Start by cloning and installing our WebViewer AngularJS sample project:

shell
git clone https://github.com/PDFTron/webviewer-angularjs-sample.git cd webviewer-angularjs-sample npm install npm start
fullscreen
Copy

And that's it! You've now got a robust and reliable PDF viewer that's easy to customize.

To integrate this into your own app, simply use the directive provided in the sample.

JavaScript
angular.module('components', []) .directive('webviewer', function() { return { restrict: 'E', scope: {}, controller: function($scope, $element) { WebViewer({ path: 'lib', // path to the PDFTron 'lib' folder on your server initialDoc: 'https://pdftron.s3.amazonaws.com/downloads/pl/webviewer-demo.pdf' }, document.getElementById('viewer')) .then(function(instance) { var docViewer = instance.docViewer; docViewer.on('documentLoaded', function() { // call methods relating to document processing }); }); }, template: "<div id='viewer' style='width: 1024px; height: 600px; margin: 0 auto;'></div>", replace: true }; })
fullscreen
Copy

Conclusion

Building a PDF Viewer with AngularJS and PDF.js can be straightforward, but once you start needing more advanced features, 100% reliability, or high-fidelity rendering, open source may not be the best approach.

PDFTron WebViewer has hundreds of features, support for 30+ file formats, a proven rendering engine built right in, and it's simple to integrate with Angular projects.

Check out documentation for our JavaScript PDF library, and get started with your free trial.

If you have any questions about PDFTron's PDF SDK, please feel free to get in touch!

You can find the source code for this blog post at Github.