Browser API
PDFDownloadLink
Renders an <a> element whose href points at the generated PDF blob and whose download attribute carries your filename. It runs usePDF internally, so you never manage the render loop yourself.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
document | DocumentTree | — | A prebuilt document tree ({ type, props, children }), for react-pdf API parity. Optional — prefer the document slot. |
fileName | string | 'document.pdf' | Value of the anchor's download attribute. |
document takes a plain document tree object. To compose your PDF with the usual components, use the document slot instead. Slots
| Prop | Type | Default | Description |
|---|---|---|---|
document | slot | — | Your <Document> component. Rendered into a hidden container; its assembled tree is handed to the internal pdf instance. |
default | scoped slot | — | The link label. Receives the render state: { url, blob, error, loading }. |
Events
| Prop | Type | Default | Description |
|---|---|---|---|
click | (event: MouseEvent, state: PDFState) => void | — | Emitted when the anchor is clicked, with the current render state as the second argument. |
Usage
Slot your <Document> into the document slot and use the default slot for the label:
vue
<script setup lang="ts">
import { PDFDownloadLink } from '@vuepdf/renderer'
import MyDocument from './MyDocument.vue'
</script>
<template>
<PDFDownloadLink file-name="report.pdf">
<template #document>
<MyDocument />
</template>
<template #default="{ loading }">
{{ loading ? 'Preparing...' : 'Download PDF' }}
</template>
</PDFDownloadLink>
</template>Reacting to Render State
The default slot is a scoped slot — the same state usePDF exposes:
vue
<template>
<PDFDownloadLink file-name="invoice.pdf" class="btn">
<template #document>
<InvoiceDocument :invoice="invoice" />
</template>
<template #default="{ loading, error, url }">
<span v-if="error">Failed to generate</span>
<span v-else-if="loading || !url">Generating...</span>
<span v-else>Download invoice</span>
</template>
</PDFDownloadLink>
</template> The anchor is always rendered, even while
loading is true. Until the first render finishes, href is empty — disable or relabel the link via the scoped slot if that matters for your UI. With a Prebuilt Tree
For parity with react-pdf, you can pass a document tree directly instead of slotting a component:
vue
<script setup lang="ts">
const tree = {
type: 'DOCUMENT',
props: { title: 'Report' },
children: [
{
type: 'PAGE',
props: { size: 'A4' },
children: [
{ type: 'TEXT', props: {}, children: ['Generated report'] },
],
},
],
}
</script>
<template>
<PDFDownloadLink :document="tree" file-name="report.pdf">
<template #default="{ loading }">
{{ loading ? 'Preparing...' : 'Download' }}
</template>
</PDFDownloadLink>
</template>Attributes
The component sets inheritAttrs: false and forwards every extra attribute — classes, target, ARIA attributes — onto the underlying <a>:
vue
<template>
<PDFDownloadLink
file-name="report.pdf"
class="btn"
target="_blank"
@click="onClick"
>
<template #document>
<MyDocument />
</template>
<template #default>Download</template>
</PDFDownloadLink>
</template>PDFDownloadLink is browser-only. To produce a file on the server, use renderToFile or renderToStream. See Also
- BlobProvider — same slot API, without the anchor.
- PDFViewer — inline preview in an iframe.