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.
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.
This content originally appeared on DEV Community and was authored by Fang Tanbamrung