Browser API
PDFViewer
The <PDFViewer> component renders its slotted document inside an <iframe>, giving you a live preview that re-renders as the document changes. It runs usePDF internally.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
style | Style | Style[] | string | — | Style applied to the iframe. Size the viewer here — there are no width/height props. |
className | string | — | Class applied to the iframe. |
title | string | — | Title attribute on the iframe, for accessibility. |
showToolbar | boolean | true | Shows the browser PDF toolbar, via the #toolbar fragment on the blob URL. |
document | DocumentTree | — | A prebuilt document tree ({ type, props, children }), for react-pdf API parity. Optional — prefer the default slot. |
document takes a plain document tree object. To compose your PDF with the usual components, slot it in the default slot instead. Slots
| Prop | Type | Default | Description |
|---|---|---|---|
default | slot | — | Your <Document> component. Rendered into a hidden container next to the iframe; its assembled tree drives the preview. |
Note the difference from PDFDownloadLink and BlobProvider: those take the document in a
#document slot because their default slot renders your own markup. PDFViewer renders only an iframe, so the document goes in the default slot. Events
| Prop | Type | Default | Description |
|---|---|---|---|
render | (payload: { url: string; blob: Blob }) => void | — | Emitted every time a new blob is produced, so you can wire up your own download button or upload the result. |
Exposed Methods
| Prop | Type | Default | Description |
|---|---|---|---|
download(filename?) | (filename?: string) => void | 'document.pdf' | Downloads the currently rendered document. |
getState() | () => PDFState | — | Returns the latest render state: { url, blob, error, loading }. |
Usage
Place a <Document> in the default slot and size the iframe with style:
vue
<script setup lang="ts">
import { PDFViewer } from '@vuepdf/renderer'
</script>
<template>
<PDFViewer :style="{ width: '100%', height: '600px' }">
<Document>
<Page size="A4">
<View :style="{ padding: 40 }">
<Text :style="{ fontSize: 24 }">Hello, PDF!</Text>
</View>
</Page>
</Document>
</PDFViewer>
</template><PDFViewer> is a browser component, not a PDF primitive — it belongs in your page's markup, never inside a <Page>. Wrap it in <ClientOnly> in Nuxt, since it needs URL.createObjectURL. Previewing a Component
Any component that renders a <Document> works, and updates as its props change:
vue
<script setup lang="ts">
import { PDFViewer } from '@vuepdf/renderer'
import InvoiceDocument from './InvoiceDocument.vue'
const invoice = ref({ id: '123', amount: 1500 })
</script>
<template>
<PDFViewer :style="{ width: '100%', height: '600px' }" :show-toolbar="false">
<InvoiceDocument :invoice="invoice" />
</PDFViewer>
</template>Downloads and Render Events
Listen for @render to react to each new blob, or call the exposed download() through a template ref:
vue
<script setup lang="ts">
import { PDFViewer } from '@vuepdf/renderer'
const viewer = useTemplateRef('viewer')
const onRender = ({ url, blob }: { url: string; blob: Blob }) => {
console.log('rendered', url, blob.size)
}
</script>
<template>
<PDFViewer ref="viewer" @render="onRender">
<MyDocument />
</PDFViewer>
<button @click="viewer?.download('report.pdf')">Download</button>
</template>See Also
- PDFDownloadLink — download anchor instead of a preview.
- BlobProvider — raw blob and state, no markup.
- usePDF — the composable all three are built on.