πŸš€ PDF Viewer in PrimeVue using @vue-pdf-viewer πŸ’‘



This content originally appeared on DEV Community and was authored by Fang Tanbamrung

PrimeVue gives Vue.js developers flexible UI components for building interactive user interfaces for fast Vue.js development. But when you need to build a PDF Viewer, native PDF rendering requires extra support. @vue-pdf-viewer stands out for its speed and ease of integration.

This guide explains how to use both PrimeVue and @vue-pdf-viewer together to display PDFs right in your Vue app. Set up a powerful vue pdf experience for your users, no matter how big your project grows.

Gif of get started

Step 1: Set up a Vue 3 Project

Start by setting up a new Vue 3 project using your preferred package manager (bun, pnpm, npm, yarn). Here’s an example using bun:

Create a new Vite project

bun create vite
  • Vite will prompt you for a project name and package name.
  • When Vite asks for a framework, choose Vue.
  • For the variant, select TypeScript (Vue + TS).

Step 2: Install PrimeVue and Vue PDF Viewer

Install PrimeVue

Install PrimeVue for UI elements:

bun add primevue @primeuix/themes

Install Vue PDF Viewer

Next, install the Vue PDF Viewer package, @vue-pdf-viewer/viewer:

bun add @vue-pdf-viewer/viewer

For more information on how to install Vue PDF Viewer using other package managers, check out the Installation guide.

Step 3: Set up PrimeVue

Configure the main.ts

To set up the default configuration, PrimeVue plugin is required to be installed as an application plugin. It’s lightweight and utilized for configuration purposes only.

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import PrimeVue from 'primevue/config' // 👈 here

const app = createApp(App)
app.use(PrimeVue)
app.mount('#app')

Verify your setup by adding a component to the the application. In this case, I will add a button and dialog. Each component can be imported and registered individually so that you can include only what you use for bundle optimization.

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import PrimeVue from 'primevue/config'
import Button from 'primevue/button' // 👈 here
import Dialog from 'primevue/dialog' // 👈 here

const app = createApp(App)
app.use(PrimeVue, {
  theme: {
    preset: Aura // 👈 here
  }
})

app.component('Button', Button) // 👈 here
app.component('Dialog', Dialog) // 👈 here
app.mount('#app')
<!-- App.vue -->
<script setup lang="ts">
const visible = ref(false)
</script>

<template>
  <Button label="Show" @click="visible = true" />
  <Dialog v-model:visible="visible" modal header="Dialog title" :style="{ width: '80vw' }">
    dialog content
  </Dialog>
</template>

Step 4: Create a Reusable Vue PDF Viewer Component

Next, let’s build a reusable PdfViewer component using <VPdfViewer> from @vue-pdf-viewer/viewer.

Create a file inside your components directory.

<!-- PdfViewer.vue -->
<script setup lang="ts">
import { VPdfViewer, VPVBaseProps } from '@vue-pdf-viewer/viewer'

const props = defineProps({
  ...VPVBaseProps
})
</script>

<template>
  <div style="width: 1028px; height: 700px; margin: 0 auto">
    <VPdfViewer v-bind="props" />
  </div>
</template>

Here’s what each part does:

  • VPdfViewer is the core PDF rendering component
  • VPVBaseProps includes all supported props (like src, page, zoom) so we can pass them in from a parent component.
  • We define the props using defineProps and spread VPVBaseProps. This makes the component flexible and lets you bind any supported viewer prop without redefining them manually.
  • We render <VPdfViewer> with v-bind=”props”. This automatically forwards all props from the parent to the viewer component, so it works like a wrapper you can reuse anywhere.

This setup keeps your PdfViewer.vue clean and flexible. You can now reuse it anywhere with different PDFs, zoom levels, pages, and more.

Use the PdfViewer in App.vue

For this use case, a Vue PDF Viewer component is displayed in a PrimeVue Dialog component.

First, import and register the PrimeVue Dialog component. Next, integrate the PdfViewer component into your Vue app which will be displayed in a dialog:

<!-- App.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import PdfViewer from './components/PdfViewer.vue'
const visible = ref(false)

const pdfSrc =
'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf'
</script>

<template>
  <Button label="Show" @click="visible = true" />
  <Dialog
    v-model:visible="visible"
    modal
    class="my-dialog"
    :style="{ width: '55rem', height: '55rem' }"
  >
    <template #header>
      <p :style="{ textAlign: 'center' }">Preview PDF</p>
    </template>
    <PdfViewer :src="pdfSrc" :initial-scale="1" :style="{ width: '100%', height: '100%' }" />
    <template #footer>
      <Button label="Close" @click="visible = false" />
    </template>
  </Dialog>
</template>

If you open the dialog, Vue PDF Viewer will render the PDF content. However, if you click on the print icon, the print preview will not be displayed correctly. To fix this issue, you can add styles to @media print:

<script setup lang="ts">
import { ref } from 'vue'
import PdfViewer from './components/PdfViewer.vue'
const visible = ref(false)

const pdfSrc =
'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf'
</script>

<template>
  <Button label="Show" @click="visible = true" />
  <Dialog
    v-model:visible="visible"
    modal
    class="my-dialog"
    :style="{ width: '55rem', height: '55rem' }"
  >
    <template #header>
      <p :style="{ textAlign: 'center' }">Preview PDF</p>
    </template>
    <PdfViewer :src="pdfSrc" :initial-scale="1" :style="{ width: '100%', height: '100%' }" />
    <template #footer>
      <Button label="Close" @click="visible = false" />
    </template>
  </Dialog>
</template>

<!-- add style to prevent print pdf that render on dialog -->
<style>
@media print {
  /* Hide the dialog mask */
  .p-dialog-mask {
    display: none !important;
  }
  /* Style the nearest ancestor of the Vue PDF Viewer container */
  .p-dialog-content {
    position: relative; /* Ensure it's not fixed or absolute */
    display: block !important; /* Ensure it's visible */
    overflow: visible; /* Ensure no content is clipped */
  }
}
</style>

Here’s what’s happening:

  • PdfViewer component is the wrapper we created earlier using VPdfViewer under the hood.
  • The PdfViewer component is added inside Dialog
  • We defined a sample pdfSrc string. This is the URL of the PDF you want to display. You can replace it with your own file (local or remote).
  • We pass :src=”pdfSrc” as a prop to <PdfViewer>. This binds the PDF file URL to the viewer component, which will take care of rendering it.

For more information on how @vue-pdf-viewer handles printing, here is the tutorial of Printing via PrimeVue Dialog.

And that’s it, you now have a working PDF viewer inside your Vue app! You can reuse this setup across different pages or wrap it inside a dialog for modal-style viewing if needed.

If you’d like to see the full codes for this example, check out the Stackblitz link for this article.

Looking for a Faster Setup?

If you want to skip boilerplate and get straight to building, check out Vue PDF Viewer Starter Toolkit.

It includes ready-to-use templates for:

  • Vue: Composition API (JavaScript / TypeScript)
  • Vue: Options API (JavaScript / TypeScript)
  • Nuxt (TypeScript)
  • Vue: SSR (TypeScript)
  • PrimeVue
  • Quasar
  • VitePress
  • Ionic

Each template comes with a clean folder structure and sample code so you can build a PDF viewer quickly without spending hours configuring dependencies. Just clone, customize, and go. πŸš€

Conclusion

Now that you have the files in place and the dependencies correctly installed, you now have a basic Vue PDF application set up that plays well with PrimeVue. You can customize the viewer further by exploring the options and features provided by @vue-pdf-viewer/viewer.

Explore the full list of props and events available in @vue-pdf-viewer/viewer. Pair these features with PrimeVue’s UI components, and you’ll be able to offer a user-friendly, feature-packed document viewer tailored to your users’ needs.

Hope this helped you get started! If you build something with it or run into questions, feel free to drop a comment. I’d love to hear how you’re using Vue PDF Viewer. πŸ”§πŸ“„

Gif of cat sliding down stairs


This content originally appeared on DEV Community and was authored by Fang Tanbamrung