VUEjs v2 PDF viewer based on Mozilla's PDFJS.
100% PDFJS functionality:
- zoom
- open
- download
- rotate
- text selection
- search panel
- pdf document password
- thumbnail, outline, attachments, annotation layers
Easily localized configurable panel
Cross-browser support (including IE11)
Color customization (IE11 not supported)
Buttons icons customization
Light/dark themes
Built-in typescript support
UMD/Unpkg support:
File | Size | Gzipped |
---|---|---|
vue-pdf-app.umd.min.js | 1742.89 KiB | 478.86 KiB |
vue-pdf-app.umd.js | 3115.59 KiB | 677.87 KiB |
vue-pdf-app.common.js | 3115.12 KiB | 677.71 KiB |
icons/main.css | 15 - 40 KiB (depends from browser) |
<template>
<vue-pdf-app pdf="http://example.com/sample.pdf"></vue-pdf-app>
</template>
<script>
import VuePdfApp from "vue-pdf-app";
// import this to use default icons for buttons
import "vue-pdf-app/dist/icons/main.css";
export default {
components: {
VuePdfApp
}
};
</script>
- Type:
string | null | ArrayBuffer | TypedArray
- Required:
false
- Usage:
<vue-pdf-app pdf="https://example.com/sample.pdf" />
<vue-pdf-app :pdf="ArrayBuffer" />
- Description:
true
renames document title to pdf file name - Type: boolean
- Required: false
- Default: false
- Usage:
<vue-pdf-app :title="true" />
- Type:
"dark" | "light"
- Required:
false
- Usage:
<vue-pdf-app theme="dark" />
<vue-pdf-app :theme="theme" />
<vue-pdf-app :theme.sync="theme" />
- Description: toolbar configuration. Toolbar is available by default. Specify
false
for buttons or whole group of buttons to disable them. - Type: toolbar config (see below)
- Required:
false
- Default: toolbar config
- Usage:
<vue-pdf-app :config="config" />
<script>
export default {
data() {
return {
// disable "Previous page" button
config: {
toolbar: {
toolbarViewerLeft: {
previous: false
}
}
},
// disable whole page navigation panel
config2: {
toolbar: {
toolbarViewerLeft: false
}
},
// disable whole panel
config3: {
toolbar: false
}
};
}
};
</script>
Config specification
{
sidebar: {
viewThumbnail: true,
viewOutline: true,
viewAttachments: true,
},
secondaryToolbar: {
secondaryPresentationMode: true,
secondaryOpenFile: true,
secondaryPrint: true,
secondaryDownload: true,
secondaryViewBookmark: true,
firstPage: true,
lastPage: true,
pageRotateCw: true,
pageRotateCcw: true,
cursorSelectTool: true,
cursorHandTool: true,
scrollVertical: true,
scrollHorizontal: true,
scrollWrapped: true,
spreadNone: true,
spreadOdd: true,
spreadEven: true,
documentProperties: true,
},
toolbar: {
toolbarViewerLeft: {
findbar: true,
previous: true,
next: true,
pageNumber: true,
},
toolbarViewerRight: {
presentationMode: true,
openFile: true,
print: true,
download: true,
viewBookmark: true,
},
toolbarViewerMiddle: {
zoomOut: true,
zoomIn: true,
scaleSelectContainer: true,
},
},
errorWrapper: true,
};
- Description: emitted only once when Pdfjs library is binded to vue component. Can be used to set Pdfjs config before pdf document opening.
- Arguments:
- PDFViewerApplication - pdf application
- Usage:
<vue-pdf-app @after-created="afterCreated" />
- Description: emitted when pdf is opened but pages are not rendered.
- Arguments:
- PDFViewerApplication - pdf application
- Usage:
<vue-pdf-app @open="openHandler" />
- Description: emitted when pdf document pages are rendered. Can be used to set default pages scale, for instance.
- Arguments:
- PDFViewerApplication - pdf application
- Usage:
<vue-pdf-app @pages-rendered="pagesRendered" />
<script>
export default {
methods: {
pagesRendered(pdfApp) {
setTimeout(() => (pdfApp.pdfViewer.currentScaleValue = "page-height"));
}
}
};
</script>
ℹ️ Events are triggered in the following order
after-created (once) => open => pages-rendered
Slot name | Slot props | Prop type | Description |
---|---|---|---|
toolbar-left-prepend
toolbar-left-append toolbar-left-append toolbar-middle-prepend toolbar-middle-append toolbar-right-prepend toolbar-right-append toolbar-sidebar-prepend toolbar-sidebar-append secondary-toolbar-prepend secondary-toolbar-append footer |
toggleTheme | function() | Toggle theme |
<vue-pdf-app>
<template #toolbar-left-prepend="{ toggleTheme }">
<button @click="toggleTheme" type="button">Toggle theme</button>
</template>
</vue-pdf-app>
Colors of the pdf viewer are customized via custom css properties:
<style>
/* for dark theme */
.pdf-app.dark {
--pdf-toolbar-color: black;
}
/* for light theme */
.pdf-app.light {
--pdf-toolbar-color: white;
}
</style>
Custom css properties specification
To use default icons import "vue-pdf-app/dist/icons/main.css";
.
To use custom icons you have to implement icons.css:
.vue-pdf-app-icon::before,
.vue-pdf-app-icon::after {
font-family: "your font family";
}
.vue-pdf-app-icon.zoom-out::before {
content: "icon code";
}
Toggle theme button is not implemented by default. It's up to you to decide where to place it. The button can be implemented with slots:
<vue-pdf-app>
<template #footer="{ toggleTheme }">
<button @click="toggleTheme" type="button">Toggle theme</button>
</template>
</vue-pdf-app>
English is the default language for panel.
Use <link rel="resource" type="application/l10n" href="path-to-localization-file">
in your html for localization.
See localization file examples.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="utf-8" />
<title>Vue-pdf-app demo</title>
<link
rel="stylesheet"
href="https://unpkg.com/vue-pdf-app@2.0.0/dist/icons/main.css"
/>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-pdf-app@2.0.0"></script>
<style>
body,
html {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="app" style="height: 100vh;">
<vue-pdf-app pdf="/sample.pdf"></vue-pdf-app>
</div>
<script>
new Vue({
components: {
VuePdfApp: window["vue-pdf-app"]
}
}).$mount("#app");
</script>
</body>
</html>
<template>
<div id="app">
<vue-pdf-app pdf="/sample.pdf"></vue-pdf-app>
</div>
</template>
<script lang="ts">
import "vue-pdf-app/dist/icons/main.css";
import VuePdfApp from "vue-pdf-app";
import { Component, Vue } from "vue-property-decorator";
@Component({
components: {
VuePdfApp
}
})
export default class App extends Vue {}
</script>
PDFJS is a huge package (see the library size table above). So use lazy loading to split your bundle into small pieces.
<template>
<div id="app">
<vue-pdf-app></vue-pdf-app>
</div>
</template>
<script>
import "vue-pdf-app/dist/icons/main.css";
import Loader from "./components/Loader.vue";
export default {
name: "App",
components: {
"vue-pdf-app": () => ({
component: new Promise((res) => {
return setTimeout(
() => res(import(/* webpackChunkName: "pdf-viewer" */ "vue-pdf-app")),
4000
);
}),
loading: Loader
})
}
};
</script>
You can interact with pdfjs library when pdf is opened via open
event.
<template>
<div id="app">
<div id="pdf-wrapper">
<vue-pdf-app pdf="/sample.pdf" @open="openHandler"></vue-pdf-app>
</div>
<div id="info">
<h1>PDF info:</h1>
<div v-for="item in info" :key="item.name">
<span>{{ item.name }}: {{ item.value }}</span>
<br />
</div>
</div>
</div>
</template>
<script>
import "vue-pdf-app/dist/icons/main.css";
import VuePdfApp from "vue-pdf-app";
export default {
name: "App",
components: {
VuePdfApp
},
data() {
return {
info: []
};
},
methods: {
async openHandler(pdfApp) {
this.info = [];
const info = await pdfApp.pdfDocument
.getMetadata()
.catch(console.error.bind(console));
if (!info) return;
const props = Object.keys(info.info);
props.forEach((prop) => {
const obj = {
name: prop,
value: info.info[prop]
};
this.info.push(obj);
});
}
}
};
</script>