Blog Post

How to Build a Vue.js PDF Viewer with PDF.js

Illustration: How to Build a Vue.js PDF Viewer with PDF.js

Vue.js is a frontend JavaScript framework for building single-page applications (SPAs) and user interfaces (UIs), and it’s the second-most starred GitHub repository. It enables users to create rapid prototypes and build fast and reliable applications.

In this blog post, we’ll use Vue.js to create a PDF viewer with PDF.js. PDF.js is an open source JavaScript library that allows you to view PDF files in your browser.

In the first part, we’ll look at how to create the PDF viewer with an open source library. In the second part, we’ll provide a step-by-step guide on how to integrate the PSPDFKit Vue.js PDF viewer library into the Vue.js project. Our viewer library provides some benefits beyond what PDF.js provides, including:

  • A prebuilt UI — Save time with a well-documented list of APIs when customizing the UI to meet your exact requirements.
  • Annotation tools — Draw, circle, highlight, comment, and add notes to documents with 15+ prebuilt annotation tools.
  • File support — View PNG, JPG, and TIFF files on the client side. With server deployment, users can view MS Office documents.
  • 30+ features — Easily add features like PDF editing, digital signatures, form filling, real-time document collaboration, and more.
  • Dedicated support — Deploy faster by working 1-on-1 with our developers

Requirements

To get started, you’ll need:

  • Git
  • Node.js (in this article, we’re using version 16.13.0)
  • A package manager for installing Vue CLI and importing packages — you can use npm or yarn

Creating the PDF Viewer with Open Source Libraries

There are two main PDF.js wrappers available to make the task of creating a PDF viewer with Vue.js easier: vue-pdf and pdfvuer. Let’s look at their respective advantages and disadvantages and decide which one to use.

Advantages of Using vue-pdf

  • It has around 163K monthly downloads on npm.
  • It’s easy to use, and it has an easy setup.

Disadvantages of Using vue-pdf

  • It currently doesn’t support Vue 3.
  • The library owner isn’t responsive.
  • When printing your files, you may get a bug. There’s been a solution for this since 2019, but the PR isn’t merged into the main branch.
  • It’s not actively maintained.
  • It lacks documentation and examples.

Advantages of Using pdfvuer

  • It has around 22K monthly downloads on npm.
  • It has support for Vue 2 and Vue 3.

Disadvantages of Using pdfvuer

  • It lacks documentation and examples.
  • It doesn’t have many options to customize your project.

In this blog post, we’ll use the pdfvuer library because it supports both version 2 and version 3 of Vue.js.

Installing Vue CLI

To work with Vue.js, we need to install Vue CLI (command-line interface), which is standard tooling for Vue.js. It helps you create, build, and run Vue.js applications.

You can install the CLI using npm, which comes with Node.js, or yarn:

npm install -g @vue/cli
yarn global add @vue/cli

You can check the version of Vue by running the following:

vue --version

In this blog post, we’re using Vue CLI version 4.5.15.

Creating the Project for pdfvuer

Vue CLI gives us an easy way to create our projects by using the following command:

vue create pdfvuer-example

Here, we’re using the create option with the name of the project we want to create (pdfvuer-example).

It’ll then ask some configuration questions.

Select Default (Vue 3) ([Vue 3] babel, eslint) from the list.

screen showing the vue.js project creation

Now, change the directory to pdfvuer-example:

cd pdfvuer-example

Adding the pdfvuer Library

Run the command below to install the pdfvuer library via npm or yarn. This will work with Vue 3:

npm install pdfvuer@next --save
yarn add pdfvuer@next

Displaying the PDF

Add your PDF document to the public directory. You can use our demo document as an example.

Now, go to your App.vue file inside the src directory and add the following code:

<template>
	<pdf src="example.pdf" :page="1" />
</template>

<script>
import pdf from 'pdfvuer';

export default {
	components: {
		pdf,
	},
};
</script>
  • In the script tag, we’re importing and exporting the pdf component from the pdfvuer library.

  • In the template tag, we’re creating a pdf element by passing the src attribute with the name of the PDF file. We’re also passing the page attribute with the number of the page we want to display. It’ll show the first page of our document.

When you start the app, you’ll see the PDF rendered in the browser. Use the following command to run the project:

npm run serve
yarn serve

You can see the app running at http://localhost:8080/.

💡 Tip: You can access the source code for this project on GitHub.

pdfvuer demo

As you can see, this library didn’t give us many options to customize the PDF viewer. We can only display the first page of our document, and there’s no way to navigate through the pages.

We’ll move on to the next part of the article to see how PSPDFKit for Web can help us.

Building a Vue.js PDF Viewer with PSPDFKit

PSPDFKit offers a versatile PDF library that can be used to build a Vue.js PDF viewer. It provides more than 30 out-of-the-box features, including:

You can integrate it into your new or existing Vue.js projects with a couple of steps.

Now, let’s go back to our tutorial and see how to integrate PSPDFKit into your Vue.js project.

  1. Create a new Vue.js project for PSPDFKit integration:

vue create pspdfkit-vue-project

This will ask some configuration questions.

  1. Select Default (Vue 3) ([Vue 3] babel, eslint) from the list, and change the directory to pspdfkit-vue-project:

cd pspdfkit-vue-project

Adding PSPDFKit

  1. Install pspdfkit as a dependency with npm or yarn:

npm install pspdfkit
yarn add pspdfkit
  1. Now, we can start building our Vue.js project. First, let’s create a js directory under the public directory. Go to your terminal and run:

mkdir -p public/js
  1. Copy the PSPDFKit for Web library assets to the public/js directory:

cp -R ./node_modules/pspdfkit/dist/pspdfkit-lib public/js/pspdfkit-lib

This will copy the pspdfkit-lib directory from within node_modules/ into the public/js/ directory to make it available to the SDK at runtime.

Displaying the PDF

  1. Add the PDF document you want to display to the public directory. You can use our demo document as an example.

  2. Add a component wrapper for the PSPDFKit library and save it as src/components/PSPDFKitContainer.vue:

// src/components/PSPDFKitContainer.vue

<template>
	<div class="pdf-container"></div>
</template>

<script>
import PSPDFKit from 'pspdfkit';

export default {
	name: 'PSPDFKit',
	/**
	 * The component receives the `pdfFile` prop, which is type of `String` and is required.
	 */
	props: {
		pdfFile: {
			type: String,
			required: true,
		},
	},
	/**
	 * We wait until the template has been rendered to load the document into the library.
	 */
	mounted() {
		this.loadPSPDFKit().then((instance) => {
			this.$emit('loaded', instance);
		});
	},
	/**
	 * We watch for `pdfFile` prop changes and trigger unloading and loading when there's a new document to load.
	 */
	watch: {
		pdfFile(val) {
			if (val) {
				this.loadPSPDFKit();
			}
		},
	},
	/**
	 * Our component has the `loadPSPDFKit` method. This unloads and cleans up the component and triggers document loading.
	 */
	methods: {
		async loadPSPDFKit() {
			PSPDFKit.unload('.pdf-container');
			return PSPDFKit.load({
				// To access the `pdfFile` from props, use `this` keyword.
				document: this.pdfFile,
				container: '.pdf-container',
			});
		},
	},

	/**
	 * Clean up when the component is unmounted so it's ready to load another document (not needed in this example).
	 */
	beforeUnmount() {
		PSPDFKit.unload('.pdf-container');
	},
};
</script>

<style scoped>
.pdf-container {
	height: 100vh;
}
</style>

Let’s look at what’s happening in our component:

  • The template section is rendering a div with the pdf-container class. This will help us declaratively bind the rendered DOM to the underlying component instance’s data.

  • The script section is defining a Vue.js instance named PSPDFKit and creating methods for mounting, loading, and unloading PDF files into the pdf-container.

  • The style section is defining the height of the container.

  1. Now, replace the contents of src/App.vue with the following:

// src/App.vue

<template>
	<div id="app">
		<label for="file-upload" class="custom-file-upload">
			Open PDF
		</label>
		<input
			id="file-upload"
			type="file"
			@change="openDocument"
			class="btn"
		/>
		<PSPDFKitContainer :pdfFile="pdfFile" @loaded="handleLoaded" />
	</div>
</template>

<script>
import PSPDFKitContainer from '@/components/PSPDFKitContainer';

export default {
	data() {
		return {
			pdfFile: this.pdfFile || '/example.pdf',
		};
	},
	/**
	 * Render the `PSPDFKitContainer` component.
	 */
	components: {
		PSPDFKitContainer,
	},
	/**
	 * Our component has two methods — one to check when the document is loaded, and the other to open the document.
	 */
	methods: {
		handleLoaded(instance) {
			console.log('PSPDFKit has loaded: ', instance);
			// Do something.
		},

		openDocument() {
			// To access the Vue instance data properties, use `this` keyword.
			if (this.pdfFile) {
				window.URL.revokeObjectURL(this.pdfFile);
			}
			this.pdfFile = window.URL.createObjectURL(
				event.target.files[0],
			);
		},
	},
};
</script>

<style>
#app {
	text-align: center;
	color: #2c3e50;
}

body {
	margin: 0;
}

input[type='file'] {
	display: none;
}

.custom-file-upload {
	border: 1px solid #ccc;
	border-radius: 4px;
	display: inline-block;
	padding: 6px 12px;
	cursor: pointer;
	background: #4a8fed;
	padding: 10px;
	color: #fff;
	font: inherit;
	font-size: 16px;
	font-weight: bold;
}
</style>
  • In the template section, we have a file upload input and the PSPDFKitContainer component.

Information

Vue.js uses directives to handle some types of functionality. For the input field, we’re using the 'v-on' directive to attach an event listener to the element. In our case, it’s the 'change' event. There’s a shortcut to 'v-on' that removes the keyword and uses an '@' symbol instead.

v-on:change="openDocument"
v-on:loaded="handleLoaded"
// or
@change="openDocument"
@loaded="handleLoaded"

Similar to the input field, for the PSPDFKitContainer component, we’re using the v-bind directive to bind the pdfFile property to the pdfFile property of the component and attaching an event listener for the loaded event:

<PSPDFKitContainer :pdfFile="pdfFile" @loaded="handleLoaded" />
  • In the script section, you can see the implementation of the handleLoaded and openDocument methods. Also, there’s a data function that returns the pdfFile property.

The data keeps track of reactive state within the current component. It’s always a function and returns an object. The object’s top-level properties are exposed via the component instance.

  • In the style section, we have styles for custom file input, and there are some general styles for the app.

  1. Start the app:

npm run serve
yarn serve

You can see the application running on localhost:8080.

If you can’t see your PDF file rendered in the browser, make sure you actually uploaded a PDF file inside the public directory.

In the demo application, we can open different PDF files by clicking the Open PDF button. We can add signatures, annotations, stamps, and more.

💡 Tip: All the finished code is available on GitHub. 😎 You can find the example code for Vue 2 in the vue-2 branch.

Conclusion

In this tutorial, we looked at how to build both a Vue.js PDF viewer with an open source library and a PSPDFKit Vue.js PDF viewer that allows you to display and render PDF files in your Vue.js application.

We created similar how-to blog posts using different web frameworks and libraries:

Open source Vue.js libraries are good options if you want to build the UI and features yourself. However, this can get complicated easily, as you may not get the support you need. Opting for a commercial solution lets you focus on other areas of your business and move up the value chain.

At PSPDFKit, we offer a commercial, feature-rich, and completely customizable JavaScript PDF library that’s easy to integrate and comes with well-documented APIs to handle advanced use cases. Try it for free, or visit our demo to see it in action.

Related Products
Share Post
Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
TUTORIALS  |  Web • PDF.js • JavaScript • How To • PDF Viewer

How to Print PDFs Using PDF.js

BLOG  |  Web • C++ • WebAssembly

Render Performance Improvements in PSPDFKit for Web

PRODUCT  |  Web

Handling Browser Support of Media Files in PSPDFKit for Web