vue-pdf doesn't refresh on src change

2.8k Views Asked by At

I'm using the latest vue-pdf package to display pdf files in my app. I built this component, PdfViewer:

<template>
  <div class="fill-height pdf-container">
    <template v-if="src && numberOfPages">
      <pdf
        v-for="page in numberOfPages"
        :key="`${fileName}-${page}`"
        :src="src"
        :page="page"
      />
    </template>
  </div>
</template>
import { mapGetters } from 'vuex'
import pdf from 'vue-pdf'

export default {
  props: {
    fileName: {
      type: String,
      required: true
    }
  },
  components: {
    pdf
  },
  data() {
    return {
      src: null,
      numberOfPages: 0
    }
  },
  computed: {
    ...mapGetters({
      getAttachments: 'questions/getAttachments'
    })
  },
  methods: {
    init() {
      if (this.fileName) {
        let url = this.getAttachments[this.fileName]
        let loadingTask = pdf.createLoadingTask(url)
        this.src = loadingTask
        this.src.promise.then(pdf => {
          this.numberOfPages = pdf.numPages
        })
      }
    },
  },
  watch: {
    fileName() {
      this.init()
    }
  },
  beforeMount() {
    this.init()
  }
}

Basically I'm receiving a fileName as a prop, then look for its URL in the object I receive in getAttachments getter. The file names are in different list component.

It works fine on the first run and the first file is loaded and displayed successfully. But once clicked on another file name - nothing being displayed. I do receive the file name prop and it does find the URL, but the file doesn't display. Even when I click on the file that has already been displayed - now it doesn't.

I thought maybe it has something to do with src and numberOfPages property, so I tried to reset them before loading the file:

init() {
      if (this.fileName) {
        this.src = null
        this.numberOfPages = 0
        let url = this.getAttachments[this.fileName]
        let loadingTask = pdf.createLoadingTask(url)
        this.src = loadingTask
        this.src.promise.then(pdf => {
          this.numberOfPages = pdf.numPages
        })
      }
    }

Alas, same result. And in the console I see the following warning from pdf.worker.js: Warning: TT: invalid function id: 9

Have no idea what it means.

Any help, please?

EDIT

I tried to do that with async/await and forceUpdate:

async init() {
      if (this.fileName) {
        this.src = null
        this.numberOfPages = 0
        let url = this.getAttachments[this.fileName]
        let loadingTask = await pdf.createLoadingTask(url)
        await loadingTask.promise.then(pdf => {
          this.src = url
          this.numberOfPages = pdf.numPages
        })
        this.$forceUpdate()
      }
    }

That also didn't help. But I found out that once I change the passed fileName, the code does go to the init() method, but for some reason it skips the loadingTask.promise.then part, doesn't go in. I have to idea why.

3

There are 3 best solutions below

0
Igal On

Well, apparently there's some issue with vue-pdf library. Eventually I solved it by setting timeout when assigning fileName prop and re-rendering the component:

<PdfViewer v-if="selectedFileName" :fileName="selectedFileName" />
onFileNameSelected(fileName) {
  this.selectedFileName = null
  setTimeout(() => {
    this.selectedFileName = fileName
  }, 0)
}

And then in the PdfViewer component it's just:

created() {
  this.src = pdf.createLoadingTask(this.getAttachments[this.fileName])
},
mounted() {
  this.src.promise.then(pdf => {
    this.numberOfPages = pdf.numPages
  })
}

That did the trick for me, though feels kinda hacky.

0
Legit007 On

If someone ever stumbles accross this. Heres the Problem, the key needs to change, only than the pdf system refreshes it selfs. Its described here: https://github.com/arkokoley/pdfvuer/issues/28

i solved it, with just these lines:

 this.pdf_options.numPages = this.pdf_options.numPages +1;
      if(isNaN(this.pdf_options.numPages)) {
        this.pdf_options.numPages = 0;
      }

Where this.pdf_options.numPages =

 <pdf
      :src="pdfdata"
      v-for="i in numPages"
      :key="i"
      :page="i"
      @loading="loaded"
    />

page in the pdf component

0
Artem Pichugin On

For me works https://tato30.github.io/VuePDF and

<VuePDF
   :pdf="pdf"
   fit-parent
   :ref="
     (el) => {
       vuePDFRef = el
      }
    "
   />