How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (2023)

In this article (a four-minute read), you’ll learn how to quickly build a PDF viewer with Vue.js and PDF.js, a popular, open-source PDF viewer.

Here’s what we’re going to build.

The source code for this project is available in our Git repo.

Prerequisites

Step 1 - Install Vue CLI

The Vue CLI makes it a lot easier to scaffold a new project from the Node.js command line. To install it globally, we will open our Node.js terminal and type the following command:

npm install -g @vue/cli

Step 2 - Create the Project

Vue has two ways for creating a project. We can use the command line, or we can use the Vue GUI, which is a graphical user interface that guides you through the creation process. We’re going to use the command line to generate our Vue project:

vue create vue-pdfjs-viewer-sample

We’ll use the default (babel, eslint) preset, which will install Vue.js and the other dependencies needed for our project.

We’ll start our local server by running:

cd vue-pdfjs-viewer-samplenpm run serve

Navigate to http://localhost:3000/ and you’ll see our default welcome screen:

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (1)

Step 3 - Implementing PDF.js

We will now integrate the open-source PDF.js library into our project to render a PDF inside our app. We will start by downloading the latest stable release from GitHub and then extracting the contents into a new public/lib folder.

We will also need a PDF file to view, which we will place in the web folder. You can use your own or download one from here.

The new file structure in our public folder will look like the following. (It’s OK to have a different PDF.js version number.)

public├── lib│ ├── pdfjs-2.3.200-dist| ├── build| ├── ...| ├── web| ├── my-pdf-file.pdf| ├── ...| ├── LICENSE├── favicon.ico└── index.html

Step 4 - Create Vue Component

Next, let’s create a basic Vue component for our PDF viewer called PDFJSViewer.vue, located under src/components. Here’s the code:

<template><div> <iframe height="100%" width=100% :src="`${getFilePath}`" ></iframe></div></template><script>export default { name: 'PDFJSViewer', props: { fileName: String, path:String }, computed:{ getFilePath: () => { if(this.fileName!==''){ return this.path +'?file=' + this.fileName } return this.path } }}</script><style scoped>div { width: 50%; height: 79vh; min-width: 400px;}</style>

The <template> section of our component will bind the data and render the DOM to the Vue instance. Our <div> is where we will mount our PDF.js web viewer using an <iframe>.

The <script> section is where we declare PDFJSViewer as a Vue component and allows us to pass in the PDF Viewer’s lib location, as well as the PDF filename to load.

The computed property will only re-evaluate when some of its reactive dependencies have changed. Meaning it will only re-evaluate when either path or filename have been changed.

The <style> section is where we can apply custom CSS styling, like the width and height of the viewer’s <div>.

Step 5 - Import the PDF Viewer Component

Now we will import the PDF viewer component and render it in our app.

In src/App.vue, let’s add our PDFJSViewer component to the <template> section and pass in the path to WebViewer's lib folder, along with the URL to a PDF we want to load:

&lt;template&gt; &lt;div id=&quot;app&quot;&gt; &lt;PDFJSViewer :path=&quot;`${path}`&quot; :fileName=&quot;`${name}`&quot;/&gt; &lt;/div&gt;&lt;/template&gt;

Inside of the <script> section, let’s import the component and declare it in the export statement, like this:

<script>import PDFJSViewer from './components/PDFJSViewer'export default { name: 'app', components: { PDFJSViewer }, data () { return { name: 'my-pdf-file.pdf', //change which pdf file loads path: 'lib/pdfjs-2.3.200-dist/web/viewer.html' //path of the PDF.js viewer.html } }}</script>

Our http://localhost:3000 will now display our PDF rendered inside our PDF.js viewer.

As a final and optional step, we will reorganize the toolbar by moving elements around, removing buttons, and changing the icons.

Let’s open public/lib/pdfjs-2.3.200-dist/web/viewer.html and add the following to the <head> section:

<script src="customToolbar.js"></script>

Next, we’ll create customToolbar.js inside the public/lib/pdfjs-2.3.200-dist/web folder and add the following code:

//create a new style sheetlet sheet = (function() { let style = document.createElement(&quot;style&quot;); style.appendChild(document.createTextNode(&quot;&quot;)); document.head.appendChild(style); return style.sheet; })(); function editToolBar(){ //when the page is resized, the viewer hides and move some buttons around. //this function forcibly show all buttons so none of them disappear or re-appear on page resize removeGrowRules(); /* Reorganizing the UI */ // the &#39;addElemFromSecondaryToPrimary&#39; function moves items from the secondary nav into the primary nav // there are 3 primary nav regions (toolbarViewerLeft, toolbarViewerMiddle, toolbarViewerRight) //adding elements to left part of toolbar addElemFromSecondaryToPrimary(&#39;pageRotateCcw&#39;, &#39;toolbarViewerLeft&#39;) addElemFromSecondaryToPrimary(&#39;pageRotateCw&#39;, &#39;toolbarViewerLeft&#39;) addElemFromSecondaryToPrimary(&#39;zoomIn&#39;, &#39;toolbarViewerLeft&#39;) addElemFromSecondaryToPrimary(&#39;zoomOut&#39;, &#39;toolbarViewerLeft&#39;) //adding elements to middle part of toolbar addElemFromSecondaryToPrimary(&#39;previous&#39;, &#39;toolbarViewerMiddle&#39;) addElemFromSecondaryToPrimary(&#39;pageNumber&#39;, &#39;toolbarViewerMiddle&#39;) addElemFromSecondaryToPrimary(&#39;numPages&#39;, &#39;toolbarViewerMiddle&#39;) addElemFromSecondaryToPrimary(&#39;next&#39;, &#39;toolbarViewerMiddle&#39;) //adding elements to right part of toolbar addElemFromSecondaryToPrimary(&#39;secondaryOpenFile&#39;, &#39;toolbarViewerRight&#39;) /* Changing icons */ changeIcon(&#39;previous&#39;, &#39;icons/baseline-navigate_before-24px.svg&#39;) changeIcon(&#39;next&#39;, &#39;icons/baseline-navigate_next-24px.svg&#39;) changeIcon(&#39;pageRotateCcw&#39;, &#39;icons/baseline-rotate_left-24px.svg&#39;) changeIcon(&#39;pageRotateCw&#39;, &#39;icons/baseline-rotate_right-24px.svg&#39;) changeIcon(&#39;viewFind&#39;, &#39;icons/baseline-search-24px.svg&#39;); changeIcon(&#39;zoomOut&#39;, &#39;icons/baseline-zoom_out-24px.svg&#39;) changeIcon(&#39;zoomIn&#39;, &#39;icons/baseline-zoom_in-24px.svg&#39;) changeIcon(&#39;sidebarToggle&#39;, &#39;icons/baseline-toc-24px.svg&#39;) changeIcon(&#39;secondaryOpenFile&#39;, &#39;./icons/baseline-open_in_browser-24px.svg&#39;) /* Hiding elements */ removeElement(&#39;secondaryToolbarToggle&#39;) removeElement(&#39;scaleSelectContainer&#39;) removeElement(&#39;presentationMode&#39;) removeElement(&#39;openFile&#39;) removeElement(&#39;print&#39;) removeElement(&#39;download&#39;) removeElement(&#39;viewBookmark&#39;) } function changeIcon(elemID, iconUrl){ let element = document.getElementById(elemID); let classNames = element.className; classNames = elemID.includes(&#39;Toggle&#39;)? &#39;toolbarButton#&#39;+elemID : classNames.split(&#39; &#39;).join(&#39;.&#39;); classNames = elemID.includes(&#39;view&#39;)? &#39;#&#39;+elemID+&#39;.toolbarButton&#39; : &#39;.&#39;+classNames classNames+= &quot;::before&quot;; addCSSRule(sheet, classNames, `content: url(${iconUrl}) !important`, 0) } function addElemFromSecondaryToPrimary(elemID, parentID){ let element = document.getElementById(elemID); let parent = document.getElementById(parentID); element.style.minWidth = &quot;0px&quot;; element.innerHTML =&#39;&#39; parent.append(element); } function removeElement(elemID){ let element = document.getElementById(elemID); element.parentNode.removeChild(element); } function removeGrowRules(){ addCSSRule(sheet, &#39;.hiddenSmallView *&#39;, &#39;display:block !important&#39;); addCSSRule(sheet, &#39;.hiddenMediumView&#39;, &#39;display:block !important&#39;); addCSSRule(sheet, &#39;.hiddenLargeView&#39;, &#39;display:block !important&#39;); addCSSRule(sheet, &#39;.visibleSmallView&#39;, &#39;display:block !important&#39;); addCSSRule(sheet, &#39;.visibleMediumView&#39;, &#39;display:block !important&#39;); addCSSRule(sheet, &#39;.visibleLargeView&#39;, &#39;display:block !important&#39;); } function addCSSRule(sheet, selector, rules, index) { if(&quot;insertRule&quot; in sheet) { sheet.insertRule(selector + &quot;{&quot; + rules + &quot;}&quot;, index); } else if(&quot;addRule&quot; in sheet) { sheet.addRule(selector, rules, index); } } window.onload = editToolBar

The PDF.js primary toolbar is broken down into 3 regions:

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (2)

The secondary toolbar is accessed via the chevron icon in the right region:

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (3)

We can move elements from the secondary toolbar into the left, middle, or right regions of the primary toolbar with the addElemFromSecondaryToPrimary function in customToolbar.js. For example, uncommenting this line will move the counter-clockwise rotation tool to the left region of the primary toolbar:

 addElemFromSecondaryToPrimary(&#39;pageRotateCcw&#39;, &#39;toolbarViewerLeft&#39;)

If you wanted to move pageRotateCcw to the middle region instead, you’d replace toolbarViewerLeft with toolbarViewerMiddle, or toolbarViewerRight for the right region. To move a different tool, replace the pageRotateCcw ID with the element ID you want to move. (See below for a full list of element IDs.)

We can also hide elements like this:

 removeElement(&#39;print&#39;) removeElement(&#39;download&#39;)

To hide different elements, replace print or download with the element ID.

NOTE: Hiding the download and print buttons is not a bulletproof way to protect our PDF, because it’s still possible to look at the source code to find the file. It just makes it a bit harder.

We can also customize the icons for various tools by swapping out the SVG file, like this:

changeIcon(&#39;previous&#39;, &#39;icons/baseline-navigate_before-24px.svg&#39;)

In the above example, previous is the element ID, while icons/baseline-navigate_before-24px.svg is the path to the tool icon.

And that’s it!

Element ID Reference for PDF.js User Interface Customization

Here’s handy reference with the IDs of the various toolbar icons:

Toolbar IconID

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (4)

sidebarToggle

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (5)

viewFind

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (6)

pageNumber

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (7)

numPages

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (8)

zoomOut

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (9)

zoomIn

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (10)

next

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (11)

previous

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (12)

presentationMode

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (13)

openFile

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (14)

print

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (15)

download

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (16)

viewBookmark

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (17)

secondaryToolbarToggle

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (18)

scaleSelectContainer

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (19)

secondaryPresentationMode

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (20)

secondaryOpenFile

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (21)

secondaryPrint

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (22)

secondaryDownload

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (23)

secondaryViewBookmark

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (24)

firstPage

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (25)

lastPage

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (26)

pageRotateCw

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (27)

pageRotateCcw

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (28)

cursorSelectTool

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (29)

cursorHandTool

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (30)

scrollVertical

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (31)

scrollHorizontal

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (32)

scrollWrapped

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (33)

spreadNone

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (34)

spreadOdd

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (35)

spreadEven

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express (36)

documentProperties

Conclusion

As you can see, rendering a PDF inside a Vue.js app isn't difficult using open-source libraries.

Building a PDF Viewer with Vue.js is relatively straightforward, but once you want to start annotating, signing, or filling forms, you would have to implement these things yourself. See our PDF.js Build vs Buy and Guide to Evaluating PDF.js to learn more.

That’s where PDF.js Express comes in. It’s a commercial PDF.js viewer that wraps a React-based UI around the open-source PDF.js rendering engine and offers out-of-the-box features like annotations, form filling and e-signatures. It’s fully compatible with Vue.js -- check out the demo, and let us know what you think!

If you need high-fidelity rendering, increased reliability, and faster performance, you could consider PDFTron WebViewer. It’s a JavaScript PDF library that integrates with Vue.js, and offers hundreds of features, like redaction, editing, page manipulation, real-time document collaboration, digital signatures, and much more. Check out the WebViewer demo.

If you have any questions about implementing PDF.js Express in your project, please contact us and we will be happy to help!

FAQs

How to Build a PDF Viewer with Vue & PDF.js | PDF.js Express? ›

Try it in-app!

Convert files to PDFs in Adobe Express on web. In the Try a quick action menu on the Adobe Express home page, select PDF > Convert to PDF. Browse for a file on your device. Select Download.

How to generate PDF using Express JS? ›

Let's create a new express project using express generator.
  1. npm i -g express-generator express node-pdf --view=hbs cd node-pdf.
  2. npm i puppeteer-html-pdf.
  3. const options = { format: 'A4', path: 'storage/invoice.pdf' }
  4. const express = require('express'); const router = express. ...
  5. npm start.
Mar 12, 2022

How do I create a PDF reader? ›

Step by Step Implementation
  1. Step 1: Create a New Project. ...
  2. Step 2: Connect your app to Firebase. ...
  3. Step 3: Add the dependency for PDF Viewer in build.gradle file. ...
  4. Step 4: Add internet permission in your AndroidManifest.xml file. ...
  5. Step 5: Working with the activity_main.xml file. ...
  6. Step 6: Working with the MainActivity.java file.
Jan 24, 2023

How to preview PDF using JavaScript? ›

initPDFRenderer Function
  1. We need to initialize the PDF.js with a source PDF.
  2. We can use the getDocument method to get a promise which resolves to pdfData.
  3. The PDF data has a function getPage.
  4. The getPage will return a promise.
  5. Once the promise is resolved we get the page data.

Can you make PDF with Adobe Express? ›

Try it in-app!

Convert files to PDFs in Adobe Express on web. In the Try a quick action menu on the Adobe Express home page, select PDF > Convert to PDF. Browse for a file on your device. Select Download.

How to generate PDF from JSON data in node js? ›

How to create PDF document in Node. js ?
  1. Prerequisites:
  2. Step 1: Install PDF module. ...
  3. Syntax:
  4. Step 2: Installing Module for setting NodeJS environment. ...
  5. Filename: package.json.
  6. Folder Structure: We can see that the PDF file is created in root directory.
  7. Example: Here is the JavaScript code that should be written in app.
Feb 24, 2022

How to generate PDF file using NodeJS? ›

Generate PDF files using NodeJS and PDFMake
  1. Download NodeJS to the web server. ...
  2. Run and install keeping all default settings.
  3. Inside your project create a new folder named pdfmake.
  4. Proceed to that folder, start the command line and run: ...
  5. This will create index. ...
  6. Now we are ready to create PDF files.
Nov 5, 2022

How to generate PDF from HTML in node JS? ›

Create a new folder for your project and go to the directory.
  1. mkdir html-to-pdf cd html-to-pdf.
  2. npm init.
  3. npm i puppeteer.
  4. const puppeteer = require('puppeteer');
  5. // Create a browser instance const browser = await puppeteer. ...
  6. // Open URL in current page await page.

How to convert JS to PDF? ›

Online file converter: convert JS to PDF instantly
  1. Upload a document from your computer or cloud storage.
  2. Add text, images, drawings, shapes, and more.
  3. Sign your document online in a few clicks.
  4. Send, export, fax, download, or print out your document.

How to download PDF automatically using JS? ›

How to download pdf automatically using JS?
  1. 1 - User click on Button.
  2. 2 - JavaScript code run and PDF file download automatically.
  3. 3 - open file using JavaScript automatically.
  4. 4 - user fills & press submit.
  5. 5 - after submitting servlet code run and save data in DB.
Mar 18, 2021

References

Top Articles
Latest Posts
Article information

Author: Terence Hammes MD

Last Updated: 16/11/2023

Views: 5763

Rating: 4.9 / 5 (69 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.