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:

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.

linkStep 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

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

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

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

linkStep 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>

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.

linkStep 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>

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>

linkStep 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>

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.

linkStep 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.

/* 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;
}

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 the rendering inconsistencies or failures that come with PDF.js (especially the older versions). If you need more robust functionality, like annotation, form filling, or others, you would have to implement them yourself.

For 100% rendering reliability, hundreds of features out-of-the-box, and more granular control of UX, consider PDFTron WebViewer:

  • View, annotate, and collaborate in real-time
  • Watermark, stamp, form fill, sign, search, and more
  • Client-side PDF editing (without a server)
  • Document security, DRM, encryption, redaction
  • Overprint, ICC color management, color separation
  • PDF, MS Office, and 30+ formats

Check out our online demo.

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

linkIntegrating PDFTron WebViewer Into Angular Projects

Start by cloning our WebViewer Angular sample project:

# command line
git clone https://github.com/PDFTron/webviewer-angular-sample.git
cd webviewer-angular-sample

Then sign up for a free trial, and download the latest version of WebViewer. Once downloaded, copy the files from the WebViewer/lib folder and paste them to your project's src/assets/webviewer folder.

Then from the command line:

# command line
npm install
npm start

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

linkConclusion

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 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 our online demo or try it free.

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.