I'm trying to load a multipage pdf from an API into vue.js using the vue-pdf library.
I have can successfully load the pdf and render the 1st page as described in this earlier question here
I've followed the instructions given in The Documentation and tried a with / without using a loadingTask and using different options for the number of pages.
I've attached the code below. this version shows no page number and no pdf. The console has the "loadPdf called" and "success" log messages and no errors.
<template>
<div>
<h3>page count is {{ numPages }}</h3>
<pdf v-for="i in numPages" :key="i" :page="i" :src="pdfsrc"></pdf>
</div>
</template>
<script>
import pdf from "vue-pdf";
import axios from "axios";
import ActiveDirectoryService from "@/services/ActiveDirectoryService.js";
export default {
components: {
pdf
},
props: {
exportId: String
},
data() {
return {
pdfsrc: null,
numPages: null,
objectUrl: null
};
},
mounted() {
if (this.pdfsrc === null) return;
this.pdfsrc.promise.then(pdf => {
this.numPages = pdf.numPages;
});
},
methods: {
loadPdf() {
console.log("loadPdf called");
return axios
.get(`${process.env.VUE_APP_API_INTRANET}/pdf`, {
responseType: "blob"
})
.then(response => {
console.log("Success", response);
const blob = new Blob([response.data]);
const objectUrl = URL.createObjectURL(blob);
this.pdfsrc = pdf.createLoadingTask(objectUrl);
})
.catch(console.error); //
},
clearBuffer() {
if (this.objectUrl !== null) {
URL.revokeObjectURL(this.objectUrl);
this.pdfsrc = null;
this.objectUrl = null;
}
}
},
watch: {
exportId: function(oldVal, newVal) {
console.log("id Changed api for pdf.");
this.loadPdf();
}
},
created() {
console.log("created with id ", this.exportId);
this.loadPdf();
},
beforeDestroy() {
this.clearBuffer();
}
};
</script>
<style scoped></style>
I'm testing with a small 3 page pdf at 46kb in total. The closest I have come to getting this to work is to hard code the number of pages to 3 which renders the pdf correctly. eg
<pdf v-for="i in 3" :key="i" :page="i" :src="pdfsrc"></pdf>
It works but obviously not a solution!
I've also tried other ways to load 'numPages' such as adding this to pdf
@num-pages="numPages = $event"
and using a computed that returns this.pdf.numPages
but so far all have failed.
I've also tried moving the promise to get numpages into the loadPdf method like so
.then(response => {
console.log("Success", response);
const blob = new Blob([response.data]);
const objectUrl = URL.createObjectURL(blob);
this.pdfsrc = pdf.createLoadingTask(objectUrl);
this.pdfsrc.promise.then(pdf => {
this.numPages = pdf.numPages;
});
})
.catch(console.error); //
which also doesn't work.
Update
I've peppered the code with log statements as requested. All looks like it should be working.
.then(response => {
console.log("Success", response);
const blob = new Blob([response.data]);
const objectUrl = URL.createObjectURL(blob);
this.pdfsrc = pdf.createLoadingTask(objectUrl);
console.log("this.pdfsrc.promise", this.pdfsrc.promise);
this.pdfsrc.promise.then(pdf => {
console.log("pdf in callback", pdf);
this.numPages = pdf.numPages;
console.log(
`this.numPages: ${this.numPages} pdf.numPages: ${pdf.numPages} `
);
console.log(this);
});
})
Update 2
I've cleaned up my example and upon removing this line
@num-pages="numPages = $event"
from the template it all started working! I've traced back through the changes in code and it seems that wrapping the object url in a loadingTask and moving the promise to the loadPdf() method is what fixed it.