Creating Your Own Toolbar
Vue PDF Viewer’s default toolbar provides convenient, out-of-the-box controls for navigating and manipulating PDF documents. However, there may be cases where you need a custom UI or prefer a more minimal or specialized set of tools.
In this tutorial, you will learn how to replace Vue PDF Viewer’s default toolbar with a fully customized set of controls using the Instance API with the following steps:
- Disable the default toolbar
- Build your own toolbar with:
- Navigation controls
- Zoom functionality
- Download capabilities
- Print controls
- Combine everything into a completely new toolbar
Overview of Custom Toolbar
In the example below, we will be creating a toolbar with basic functions such as zoom, page navigation file download and print.
Disabling the Default Toolbar
Before creating a custom toolbar, you will need to remove the built-in toolbar provided by Vue PDF Viewer. This can be done by setting the :toolbar-options
prop to false
.
<VPdfViewer :toolbar-options="false" />
With the toolbar disabled, the Viewer will no longer display the default controls, giving you a clean slate to build your own.
Time to Building Your Own Toolbar
Now that the default toolbar is disabled, we will create a fully customized toolbar tailored to your application's design and functionality.
Our toolbar includes:
- Navigation controls – Buttons for navigating pages
- Zoom controls – Buttons for increasing and decreasing zoom levels
- Download option – A button to download the PDF
- Print feature – A button to print the PDF
To access the API, we will use Vue.js ref
to create a reference to the Viewer instance.
<script lang="ts" setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer';
const vpvRef = ref<InstanceType<typeof VPdfViewer>>();
</script>
<template>
<VPdfViewer ref="vpvRef" />
</template>
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer';
const vpvRef = ref(null);
</script>
<template>
<VPdfViewer ref="vpvRef" />
</template>
<script lang="ts">
import { VPdfViewer } from "@vue-pdf-viewer/viewer";
export default {
components: {
VPdfViewer,
},
data() {
return {
vpvRef: null,
}
},
}
</script>
<template>
<VPdfViewer ref="vpvRef" />
</template>
<script>
import { VPdfViewer } from "@vue-pdf-viewer/viewer";
export default {
components: {
VPdfViewer,
},
data() {
return {
vpvRef: null,
}
},
}
</script>
<template>
<VPdfViewer ref="vpvRef" />
</template>
Next, we will start creating the toolbar component by setting up the basic structure.
For styling of the toolbar, Tailwind CSS and Font Awesome icons will be used.
INFO
To use Font Awesome icons, you will need to include Font Awesome in your project. For simplicity, we will use a CDN in our example to make it easy to follow along.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
In the sections below, we will walkthrough by adding each function separately before combining the codes at the end.
Zoom-in & Zoom-out Function
Vue PDF Viewer provides a Zoom Controller as part of its Instance API, allowing you to implement custom zoom controls within your application.
We will use Vue's ref
and computed functions to track and adjust the current zoom level dynamically.
In this section, we will implement:
- Zoom In – Increase the zoom level by 0.25
- Zoom Out – Decrease the zoom level by 0.25
The code snippet below demonstrates how to integrate these custom zoom controls into your toolbar.
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
// Access zoom controls
const zoomControl = computed(() => vpvRef.value?.zoomControl);
// Track current zoom level
const currentScale = computed(() => {
return zoomControl.value?.scale;
});
// Handle different zoom actions
const handleZoomTool = (type: "in" | "out") => {
const zoomCtrl = unref(zoomControl);
if (!zoomCtrl) return;
const scale = unref(currentScale);
if (type === "in") {
scale && zoomCtrl.zoom(scale + 0.25); // Zoom in by 0.25
} else if (type === "out") {
scale && zoomCtrl.zoom(scale - 0.25); // Zoom out by 0.25
} else {
zoomCtrl.zoom(type as ZoomLevel); // Set to specific zoom level
}
};
</script>
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, unref } from 'vue'
const vpvRef = ref(null)
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => {
return zoomControl.value?.scale
})
const handleZoomTool = (type) => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === "in") {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === "out") {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
</script>
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => zoomControl.value?.scale)
const handleZoomTool = (type: 'in' | 'out') => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === 'in') {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === 'out') {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
return {
vpvRef,
handleZoomTool,
zoomControl,
currentScale
}
}
})
</script>
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => zoomControl.value?.scale)
const handleZoomTool = (type) => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === 'in') {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === 'out') {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
return {
vpvRef,
handleZoomTool,
zoomControl,
currentScale
}
}
})
</script>
<template>
<div class="py-2 px-2">
<div class="flex flex-col gap-4 justify-self-center">
<div class="flex items-center gap-4 text-[#7862FF] bg-pale-blue border-[#D7D1FB] rounded-lg p-2 justify-center">
<!-- Zoom out button -->
<button @click="() => handleZoomTool('out')">
<i class="fa-solid fa-magnifying-glass-minus"></i>
</button>
<!-- Zoom in button -->
<button @click="() => handleZoomTool('in')">
<i class="fa-solid fa-magnifying-glass-plus"></i>
</button>
</div>
</div>
</div>
</template>
Page Control Function
Vue PDF Viewer provides a Page Controller via its Instance API, allowing you to programmatically control page navigation and track the current position.
In this section, we will implement:
- Previous Page – Navigate to the previous page unless already on the first page.
- Next Page – Navigate to the next page unless already on the last page.
- Page Input – Allow users to enter a page number and navigate directly to that page.
The following code snippet demonstrates how to integrate custom page navigation controls into your toolbar.
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
const vpvRef = ref<InstanceType<typeof VPdfViewer>>();
// Computed properties to access various controls from the viewer
const pageControl = computed(() => vpvRef.value?.pageControl);
const currentPageInput = computed(() => pageControl.value?.currentPage);
const searchControl = computed(() => vpvRef.value?.searchControl);
// Get the total number of search matches when searching in the PDF
const totalMatches = computed(
() => searchControl?.value?.searchMatches?.totalMatches,
);
// Function to navigate to the previous page
const prevPage = () => {
// Check if we're on the first page
const isFirstPage = pageControl.value?.currentPage === 1;
if (isFirstPage) {
return; // Don't do anything if we're already on first page
}
// Navigate to previous page
pageControl.value?.goToPage(pageControl.value?.currentPage - 1);
};
// Function to navigate to the next page
const nextPage = () => {
// Check if we're on the last page
const isLastPage =
pageControl.value?.currentPage === pageControl.value?.totalPages;
if (isLastPage) {
return; // Don't do anything if we're already on last page
}
// Navigate to next page
pageControl.value?.goToPage(pageControl.value?.currentPage + 1);
};
// Handle Enter key press in the page input field
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key === "Enter") {
handlePageInput(event);
}
};
// Computed properties to control button disabled states
const isNextPageButtonDisable = computed(
() => pageControl.value?.currentPage === pageControl.value?.totalPages,
);
const isPreviousPageButtonDisable = computed(
() => pageControl.value?.currentPage === 1,
);
</script>
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed } from 'vue'
const vpvRef = ref(null)
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
</script>
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
return {
vpvRef,
pageControl,
currentPageInput,
searchControl,
totalMatches,
prevPage,
nextPage,
handleKeyPress,
isNextPageButtonDisable,
isPreviousPageButtonDisable
}
}
})
</script>
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
return {
vpvRef,
pageControl,
currentPageInput,
searchControl,
totalMatches,
prevPage,
nextPage,
handleKeyPress,
isNextPageButtonDisable,
isPreviousPageButtonDisable
}
}
})
</script>
<template>
<div>
<!-- The rest of your code -->
<!-- Previous page button -->
<button @click="prevPage" :disabled="isPreviousPageButtonDisable">
<i class="fa-solid fa-chevron-up" />
</button>
<!-- Page number input and total pages display -->
<div class="flex items-center text-sm font-normal">
<input
v-model="currentPageInput"
class="w-12 h-8 rounded-sm focus:outline-none pl-2"
@keypress="handleKeyPress"
/>
<span class="pl-1">
/{{ pageControl?.totalPages }}
</span>
</div>
<!-- Next page button -->
<button @click="nextPage" :disabled="isNextPageButtonDisable">
<i class="fa-solid fa-chevron-down" />
</button>
</div>
</template>
Print Control Function
Vue PDF Viewer provides a Print Controller via its Instance API, allowing you to implement custom print functionality with progress tracking and error management.
In this section, we will implement:
- Print Button – Initiates the print process with a visible progress indicator.
- Cancel Print – Allows users to cancel an ongoing print operation.
- Progress Tracking – Monitors and logs print progress, including loading percentage and loaded pages.
- Error Handling – Detects and logs errors during printing, with automatic cancellation upon failure.
- Success Handling – Notifies when the print job completes successfully.
To dynamically manage event handlers, we use Vue’s watch function to observe changes in the printControl
object.
The following code snippet shows how to integrate custom print controls into your toolbar.
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
const vpvRef = ref<InstanceType<typeof VPdfViewer>>();
// Computed property to access print control from the PDF viewer
const printControl = computed(() => vpvRef.value?.printControl);
// Function to handle print initiation
const handlePrintTool = () => {
// Get the print control instance using Vue's unref utility
const printCtrl = unref(printControl);
// Guard clause: exit if print control is not available
if (!printCtrl) return;
// Start printing with visible progress indicator
printCtrl.print({ visibleDefaultProgress: true });
};
// Function to cancel ongoing print operation
const cancelPrint = () => {
// Get the print control instance
const printCtrl = unref(printControl);
// Guard clause: exit if print control is not available
if (!printCtrl) return;
// Cancel the print operation
printCtrl.cancel();
};
// Watch for changes in printControl to set up event handlers
watch(printControl, (printCtrl) => {
// Guard clause: exit if print control is not available
if (!printCtrl) return;
// Progress handler to track printing status
printCtrl.onProgress = (progress: any) => {
console.log("Print progress", progress.percentage, progress.loadedPages);
};
// Error handler for print failures
printCtrl.onError = (error: any) => {
console.log("Print error", error);
// Automatically cancel print job on error
cancelPrint();
};
// Success handler when printing completes
printCtrl.onComplete = () => {
console.log("Print completed");
};
});
</script>
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, unref, watch } from 'vue'
const vpvRef = ref(null)
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
</script>
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref, watch } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress: any) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error: any) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
return {
vpvRef,
printControl,
handlePrintTool,
cancelPrint
}
}
})
</script>
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref, watch } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
return {
vpvRef,
printControl,
handlePrintTool,
cancelPrint
}
}
})
</script>
<template>
<div>
<!-- The rest of your code -->
<!-- Print button -->
<button @click="handlePrintTool">
<i class="fa-solid fa-print" />
</button>
</div>
</template>
Download Function
Vue PDF Viewer provides a Download Controller as part of its Instance API, allowing you to create a custom download feature instead of using the default toolbar button.
In this section, we will implement:
- Download Button – Initiates the PDF download when clicked.
- Error Handling – Logs errors if the download process fails.
- Success Handling – Confirms successful download completion.
Using Vue’s watch function, we dynamically attach event handlers to the downloadControl
object when it becomes available.
The code snippet below shows how to integrate a custom download button into your toolbar.
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
const vpvRef = ref<InstanceType<typeof VPdfViewer>>();
// Computed property to access download control from the PDF viewer
const downloadControl = computed(() => vpvRef.value?.downloadControl);
// Function to handle file download
const handleDownloadFile = () => {
// Get the download control instance using Vue's unref utility
const downloadCtrl = unref(downloadControl);
// Guard clause: exit if download control is not available
if (!downloadCtrl) return;
// Trigger the download
downloadCtrl.download();
};
// Watch for changes in downloadControl to set up event handlers
watch(downloadControl, (downloadCtrl) => {
// Guard clause: exit if download control is not available
if (!downloadCtrl) return;
// Error handler for download failures
downloadCtrl.onError = (error: any) => {
console.log("Download error", error);
};
// Success handler when download completes
downloadCtrl.onComplete = () => {
console.log("Download completed");
};
});
</script>
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, unref, watch } from 'vue'
const vpvRef = ref(null)
const downloadControl = computed(() => vpvRef.value?.downloadControl)
const handleDownloadFile = () => {
const downloadCtrl = unref(downloadControl)
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
</script>
```vue [Options TS]
<script lang="ts">
import { defineComponent, ref, computed, watch } from 'vue'
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const downloadControl = computed(() => {
return vpvRef.value?.downloadControl
})
const handleDownloadFile = () => {
const downloadCtrl = downloadControl.value
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error: any) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
return {
vpvRef,
downloadControl,
handleDownloadFile
}
}
})
</script>
<script>
import { defineComponent, ref, computed, watch } from 'vue'
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const downloadControl = computed(() => {
return vpvRef.value?.downloadControl
})
const handleDownloadFile = () => {
const downloadCtrl = downloadControl.value
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
return {
vpvRef,
downloadControl,
handleDownloadFile
}
}
})
</script>
<template>
<div>
<!-- The rest of your code -->
<!-- Download button -->
<button @click="handleDownloadFile">
<i class="fa-solid fa-download" />
</button>
</div>
</template>
Complete Example
Now that we have covered each feature step by step, let's assemble the complete custom toolbar in a single file.
Here is the complete example that includes custom toolbar controls for downloading, zooming, page navigation, and printing.
<script setup lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
const zoomControl = computed(() => vpvRef.value?.zoomControl);
const currentScale = computed(() => {
return zoomControl.value?.scale;
});
const handleZoomTool = (type: "in" | "out") => {
const zoomCtrl = unref(zoomControl);
if (!zoomCtrl) return;
const scale = unref(currentScale);
if (type === "in") {
scale && zoomCtrl.zoom(scale + 0.25);
} else if (type === "out") {
scale && zoomCtrl.zoom(scale - 0.25);
} else {
zoomCtrl.zoom(type as ZoomLevel);
}
};
const pageControl = computed(() => vpvRef.value?.pageControl);
const currentPageInput = computed(() => pageControl.value?.currentPage);
const searchControl = computed(() => vpvRef.value?.searchControl);
const totalMatches = computed(
() => searchControl?.value?.searchMatches?.totalMatches,
);
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1;
if (isFirstPage) {
return;
}
pageControl.value?.goToPage(pageControl.value?.currentPage - 1);
};
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1;
if (isFirstPage) {
return;
}
pageControl.value?.goToPage(pageControl.value?.currentPage - 1);
};
const nextPage = () => {
const isLastPage =
pageControl.value?.currentPage === pageControl.value?.totalPages;
if (isLastPage) {
return;
}
pageControl.value?.goToPage(pageControl.value?.currentPage + 1);
};
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key === "Enter") {
handlePageInput(event);
}
};
const isNextPageButtonDisable = computed(
() => pageControl.value?.currentPage === pageControl.value?.totalPages,
);
const isPreviousPageButtonDisable = computed(
() => pageControl.value?.currentPage === 1,
);
const printControl = computed(() => vpvRef.value?.printControl);
const handlePrintTool = () => {
const printCtrl = unref(printControl);
if (!printCtrl) return;
printCtrl.print({ visibleDefaultProgress: true });
};
const cancelPrint = () => {
const printCtrl = unref(printControl);
if (!printCtrl) return;
printCtrl.cancel();
};
watch(printControl, (printCtrl) => {
if (!printCtrl) return;
printCtrl.onProgress = (progress: any) => {
console.log("Print progress", progress.percentage, progress.loadedPages);
};
printCtrl.onError = (error: any) => {
console.log("Print error", error);
cancelPrint();
};
printCtrl.onComplete = () => {
console.log("Print completed");
};
});
const downloadControl = computed(() => vpvRef.value?.downloadControl);
const handleDownloadFile = () => {
const downloadCtrl = unref(downloadControl);
if (!downloadCtrl) return;
downloadCtrl.download();
};
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return;
downloadCtrl.onError = (error: any) => {
console.log("Download error", error);
};
downloadCtrl.onComplete = () => {
console.log("Download completed");
};
});
</script>
<script setup>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, unref } from 'vue'
const vpvRef = ref(null)
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => {
return zoomControl.value?.scale
})
const handleZoomTool = (type) => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === "in") {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === "out") {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
const downloadControl = computed(() => vpvRef.value?.downloadControl)
const handleDownloadFile = () => {
const downloadCtrl = unref(downloadControl)
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
</script>
<script lang="ts">
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref<InstanceType<typeof VPdfViewer>>()
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => zoomControl.value?.scale)
const handleZoomTool = (type: 'in' | 'out') => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === 'in') {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === 'out') {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event: KeyboardEvent) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress: any) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error: any) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
const downloadControl = computed(() => {
return vpvRef.value?.downloadControl
})
const handleDownloadFile = () => {
const downloadCtrl = downloadControl.value
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error: any) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
return {
vpvRef,
handleZoomTool,
zoomControl,
currentScale,
pageControl,
currentPageInput,
searchControl,
totalMatches,
prevPage,
nextPage,
handleKeyPress,
isNextPageButtonDisable,
isPreviousPageButtonDisable,
printControl,
handlePrintTool,
cancelPrint,
downloadControl,
handleDownloadFile
}
}
})
</script>
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import { ref, computed, defineComponent, unref } from 'vue'
export default defineComponent({
components: { VPdfViewer },
setup() {
const vpvRef = ref(null)
const zoomControl = computed(() => vpvRef.value?.zoomControl)
const currentScale = computed(() => zoomControl.value?.scale)
const handleZoomTool = (type) => {
const zoomCtrl = unref(zoomControl)
if (!zoomCtrl) return
const scale = unref(currentScale)
if (type === 'in') {
scale && zoomCtrl.zoom(scale + 0.25)
} else if (type === 'out') {
scale && zoomCtrl.zoom(scale - 0.25)
} else {
zoomCtrl.zoom(type)
}
}
const pageControl = computed(() => vpvRef.value?.pageControl)
const currentPageInput = computed(() => pageControl.value?.currentPage)
const searchControl = computed(() => vpvRef.value?.searchControl)
const totalMatches = computed(() => searchControl.value?.searchMatches?.totalMatches)
const isNextPageButtonDisable = computed(() =>
pageControl.value?.currentPage === pageControl.value?.totalPages
)
const isPreviousPageButtonDisable = computed(() =>
pageControl.value?.currentPage === 1
)
const prevPage = () => {
const isFirstPage = pageControl.value?.currentPage === 1
if (isFirstPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage - 1)
}
const nextPage = () => {
const isLastPage = pageControl.value?.currentPage === pageControl.value?.totalPages
if (isLastPage) return
pageControl.value?.goToPage(pageControl.value?.currentPage + 1)
}
const handleKeyPress = (event) => {
if (event.key === "Enter") {
handlePageInput(event)
}
}
const printControl = computed(() => vpvRef.value?.printControl)
const handlePrintTool = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.print({ visibleDefaultProgress: true })
}
const cancelPrint = () => {
const printCtrl = unref(printControl)
if (!printCtrl) return
printCtrl.cancel()
}
watch(printControl, (printCtrl) => {
if (!printCtrl) return
printCtrl.onProgress = (progress) => {
console.log("Print progress", progress.percentage, progress.loadedPages)
}
printCtrl.onError = (error) => {
console.log("Print error", error)
cancelPrint()
}
printCtrl.onComplete = () => {
console.log("Print completed")
}
})
const downloadControl = computed(() => {
return vpvRef.value?.downloadControl
})
const handleDownloadFile = () => {
const downloadCtrl = downloadControl.value
if (!downloadCtrl) return
downloadCtrl.download()
}
watch(downloadControl, (downloadCtrl) => {
if (!downloadCtrl) return
downloadCtrl.onError = (error) => {
console.log("Download error", error)
}
downloadCtrl.onComplete = () => {
console.log("Download completed")
}
})
return {
vpvRef,
handleZoomTool,
zoomControl,
currentScale,
pageControl,
currentPageInput,
searchControl,
totalMatches,
prevPage,
nextPage,
handleKeyPress,
isNextPageButtonDisable,
isPreviousPageButtonDisable,
printControl,
handlePrintTool,
cancelPrint,
downloadControl,
handleDownloadFile
}
}
})
</script>
<template>
<div class="py-2 px-2">
<div class="flex flex-col gap-4 justify-self-center">
<div class="flex items-center gap-4 text-[#7862FF] bg-pale-blue border-[#D7D1FB] rounded-lg p-2 justify-center">
<button @click="() => handleZoomTool('out')">
<i class="fa-solid fa-magnifying-glass-minus"></i>
</button>
<button @click="() => handleZoomTool('in')">
<i class="fa-solid fa-magnifying-glass-plus"></i>
</button>
<button @click="prevPage" :disabled="isPreviousPageButtonDisable">
<i class="fa-solid fa-chevron-up" />
</button>
<div class="flex items-center text-sm font-normal">
<input
v-model="currentPageInput"
class="w-12 h-8 rounded-sm focus:outline-none pl-2"
@keypress="handleKeyPress"
/>
<span class="pl-1">/{{ pageControl?.totalPages }}</span>
</div>
<button @click="nextPage" :disabled="isNextPageButtonDisable">
<i class="fa-solid fa-chevron-down" />
</button>
<button @click="handlePrintTool">
<i class="fa-solid fa-print" />
</button>
<button @click="handleDownloadFile">
<i class="fa-solid fa-download" />
</button>
</div>
</div>
</div>
</template>