vue-pdf icon indicating copy to clipboard operation
vue-pdf copied to clipboard

Working exemple with Nuxt

Open frederic117 opened this issue 5 years ago • 15 comments

Hello everybody Is someone could providence a working tuto for an implémentation with Nuxt? Thanks a lot

frederic117 avatar Mar 28 '19 20:03 frederic117

+1

YannicEl avatar May 02 '19 19:05 YannicEl

+1

herogui avatar Jun 03 '19 05:06 herogui

Hi! Since I had a really bad time managing how to include vue-pdf in my Nuxt.js project, may be this could help someone. This tuto shows how I managed to include vue-pdf in a vue, not as a plugin:

  • Create project npx create-nuxt-app my-project

  • Install vue-pdf npm install -s vue-pdf

  • Declare the package in nuxt.config.js

...
build: {
   vendor: ['vue-pdf'],
   extend(config, ctx) {
      config.output.globalObject = 'this'
   }
} 
...
  • Import the component in your .vue file (in the <script> tag)
<script>
var vuePdf;
if (process.browser) {
  vuePdf = require('vue-pdf').default
}
export default { 
   ...
   components: {
      vuePdf
   }
   ...
}
</script>
  • Use the component in your .vue (in the <template> tag)
<template>
   <div>
      <no-ssr>
         <vuePdf src="https://your-pdf-file.com"></vuePdf>
      </no-ssr>
   </div>
</template>
  • Run your app
npm run dev
  • If you met this error
This dependency was not found:

* babel-runtime/regenerator in ./node_modules/pdfjs-dist/lib/web/ui_utils.js

To install it, you can run: npm install --save babel-runtime/regenerator

then run

npm install -s babel-runtime

Hope it will help!

EmmanuelJego avatar Jun 23 '19 13:06 EmmanuelJego

Thank you very much @EmmanuelJego !

BobDempsey avatar Sep 04 '19 17:09 BobDempsey

I still can't make this work got window is not defined And vendor is deprecated :(

frederic117 avatar Sep 06 '19 20:09 frederic117

This should be a solution:

1- npm install -s vue-pdf

2- plugins/vue-pdf.js:

import Vue from 'vue'
import pdf from "vue-pdf";

Vue.component('pdf', pdf)

3- nuxt.config.js: Add { src: '~/plugins/vue-pdf.js', ssr: false } to plugins Will be:

plugins: [
    '~/plugins/axios',
    { src: '~/plugins/vue-pdf.js', ssr: false },
  ],

Add to extend(config, ctx) Will be:

 build: {
    extend(config, ctx) {
      config.output.globalObject = 'this'
      config.module.rules.push(
        {
          test: /\.pdf$/,
          loader: 'url-loader'
        }
      )
  },

4- In .vue file

<template>
  <div>
    <client-only placeholder="Loading...">
      <pdf
        class="pdf"
        :src="require('@/assets/example.pdf')"
        :page="1"
      ></pdf>
    </client-only>
  </div>
</template>

<script>
export default {};
</script>

<style lang="css">
.pdf {
  border: 1px solid red;
  width: 100%;
  height: 100%;
}
</style>

mryassera avatar Dec 10 '19 00:12 mryassera

 build: {
    extend(config, ctx) {
      config.output.globalObject = 'this'
      config.module.rules.push(
        {
          test: /\.pdf$/,
          loader: 'url-loader'
        }
      )
  },

is only necessary when using require inside src. Since nuxtjs has a static folder it's enough to have files like /static/123.pdf being loaded as <pdf src="/123.pdf" />

chris-aeviator avatar Feb 26 '20 10:02 chris-aeviator

Here's how I solved this with Nuxt with no webpack extensions/modifications, etc. Works with multi-paged pdf's.

  1. Install via npm
npm install -save vue-pdf
  1. Create a plugin called vue-pdf.js:
import Vue from 'vue'
import pdf from "vue-pdf";

Vue.component('vue-pdf', pdf)
  1. Add to nuxt.config.js:
plugins: [
    { src: '~/plugins/vue-pdf.js', mode: 'client' },
]
  1. In your component, do the following.
<template>
    <client-only>
        <vue-pdf class="your-pdf-class" :src="pdfSrc" :page="1" @num-pages="pdfPageCount = $event"></vue-pdf>
        <div v-if="pdfPageCount > 1">
            <div v-for="(pageNum, index) in pdfPageCount " :key="index">
                <vue-pdf class="your-pdf-class" :src="pdfSrc" :page="pageNum" v-if="pageNum > 1"></vue-pdf>
            </div>
        </div>
    </client-only>
</template>

export default {
    data() {
	return {
	    pdfSrc: '/path-to-your-pdf',
	    pdfPageCount : 0,
	}
    }
}

And that's it. Make sure you wrap your template code in <client-only>.

The import pdf from 'vue-pdf' and the logic using it in the component script (such as pdf.createLoadingTask from the examples) were causing it to break for me, so I just shifted the majority of the logic to the template.

For further modification, using the props and events in the API should be enough to get the job done.

danielrjames avatar Apr 24 '20 16:04 danielrjames

Access to fetch at 'http://127.0.0.1:1001/status/204+IDM' (redirected from 'https://cdn.filestackcontent.com/wcrjf9qPTCKXV3hMXDwK') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

this is alert returns to the console

jerrychico avatar Jul 13 '20 11:07 jerrychico

@jerrychico this is an issue with the source of your PDF - it seems like cdn.filestackcontent.com does not allow you to access their files directly in a browser. You could try to proxy the request with nuxt-proxy and see if you can bypass this issue. It does not have anything todo with vue-pdf

chris-aeviator avatar Jul 13 '20 11:07 chris-aeviator

@danielrjames First of all, thanks for your suggestion. It worked for me. However, if the PDF has 'n' pages, it will make 'n' API calls to the file - one for each page. If you open the console and you'll notice it on the network activity. I tried to import the pdf library to use the createLoadingTask() method however I get the 'missing stake frame' error. Is that what happened to you as well?

tpanthier avatar Jul 16 '20 08:07 tpanthier

@tpanthier Yes, that's what was happening for me.

I didn't realize the api was calling for each page. It's a small price to pay for a working solution, but I can see how that can be a pain if you're dealing with pdfs that are very long.

danielrjames avatar Jul 16 '20 17:07 danielrjames

@tpanthier @danielrjames
You can do this to resolve it: Plugins pdf:

import Vue from 'vue'
import pdf from 'vue-pdf'

export default function () {
  Vue.component('pdf', pdf)
  Vue.prototype.pdf = pdf
}

And in your component: this.pdfSrc = Vue.prototype.pdf.createLoadingTask(this.url)

mvn-vynguyen-dn avatar Nov 17 '20 02:11 mvn-vynguyen-dn

Here is the simplest solution :

components: {
    pdf: () => import('vue-pdf')
},

d4rkr3pt0r avatar Jul 15 '21 14:07 d4rkr3pt0r

This should be a solution:

1- npm install -s vue-pdf

2- plugins/vue-pdf.js:

import Vue from 'vue'
import pdf from "vue-pdf";

Vue.component('pdf', pdf)

3- nuxt.config.js: Add { src: '~/plugins/vue-pdf.js', ssr: false } to plugins Will be:

plugins: [
    '~/plugins/axios',
    { src: '~/plugins/vue-pdf.js', ssr: false },
  ],

Add to extend(config, ctx) Will be:

 build: {
    extend(config, ctx) {
      config.output.globalObject = 'this'
      config.module.rules.push(
        {
          test: /\.pdf$/,
          loader: 'url-loader'
        }
      )
  },

4- In .vue file

<template>
  <div>
    <client-only placeholder="Loading...">
      <pdf
        class="pdf"
        :src="require('@/assets/example.pdf')"
        :page="1"
      ></pdf>
    </client-only>
  </div>
</template>

<script>
export default {};
</script>

<style lang="css">
.pdf {
  border: 1px solid red;
  width: 100%;
  height: 100%;
}
</style>

At first thanks for showing the tuto!! Although I followed this tuto, I got an error as following.

vuePdfNoSss.vue:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<style src="./annotationLayer.css"></style>
                                                                                             
SyntaxError: Unexpected token '<'
Vue.component('vue-pdf', pdf)

Does anyone knows how to solve this error?? :( ref: https://github.com/FranckFreiburger/vue-pdf/issues/13

iret-ichihara avatar Dec 26 '22 10:12 iret-ichihara