kempsteven / vue-html2pdf

vue-html2pdf converts any vue component or element into PDF, vue-html2pdf is basically a vue wrapper only and uses html2pdf.js behind the scenes.
https://www.npmjs.com/package/vue-html2pdf
MIT License
440 stars 74 forks source link

Can't make it work in Nuxt SSR #43

Closed NanyThery closed 4 years ago

NanyThery commented 4 years ago

Could you please make a replicate of the current demo in Nuxt? I just cannot make it work following the instructions.

1) I've made the plugin file. 2) I've included as a plugin with mode: 'client' 3) I created a component with the options and the content and wrapped it into a "client-only" tag. 4) called the generate PDF

The component:

<template>
  <client-only>
    <vue-html2pdf
      ref="html2Pdf"
      :show-layout="false"
      :float-layout="true"
      :enable-download="true"
      :preview-modal="true"
      :paginate-elements-by-height="1400"
      filename="hee hee"
      :pdf-quality="2"
      :manual-pagination="false"
      pdf-format="a4"
      pdf-orientation="landscape"
      pdf-content-width="800px"
      @progress="onProgress($event)"
      @hasStartedGeneration="hasStartedGeneration()"
      @hasGenerated="hasGenerated($event)"
    >
      <section slot="pdf-content">
        <MenuGrid v-if="activeMenu" :menu="activeMenu" />
      </section>
    </vue-html2pdf>
  </client-only>
</template>

<script>
import MenuGrid from '~/components/MainFoodMenu/MenuGrid.vue'
export default {
  components: {
    MenuGrid,
  },
  layout: 'nonApp',
  data() {
    return {
      output: null,
      activeMenu: '',
    }
  },
  async fetch() {
    this.activeMenu = this.$store.state.activeMenu
  },
  async mounted() {
    this.print()
  },

  methods: {
    print() {
      this.$refs.html2Pdf.generatePdf()
    },
  },
}
</script>

The nuxt config:

const colors = require('vuetify/es5/util/colors').default

module.exports = {
  head: {
    titleTemplate: '%s - ' + process.env.npm_package_name,
    title: process.env.npm_package_name || '',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: process.env.npm_package_description || '',
      },
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: ['~/assets/css/globalStyles.css'],
  plugins: ['~/plugins/firebase.js', { src: '~/plugins/vue-html2pdf.js', mode: 'client' }],

  buildModules: [
    '@nuxtjs/eslint-module',
    '@nuxtjs/vuetify',
    "@nuxtjs/date-fns"
  ],
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/dotenv',
  ],
  axios: {},
  serverMiddleware: [],
  vuetify: {
    customVariables: ['~src/assets/variables.scss'],
    theme: {
      themes: {
        light: {
          primary: '#53783B',
          accent: colors.grey.darken3,
          secondary: colors.amber.darken3,
          info: colors.teal.lighten1,
          warning: colors.amber.base,
          error: colors.deepOrange.accent4,
          success: colors.green.accent3,
        },
      },
    },
  },
  /*
   ** Build configuration
   */
  srcDir: 'src',
  buildDir: 'functions/.nuxt',
  build: {
    extend(config, ctx) {
      // Run ESLint on save
      if (ctx.isDev && ctx.isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/,
          options: {
            fix: true
          }
        })
      }
    },
    extractCSS: true,

  },
}

The errors:

image

What I've tried:

image


  build: {

    transpile: ['vue-html2pdf']
  },

I really do not know what else to do, can you please help me? I don't seem to find any other example on how to apply it in Nuxt.

Thank you

kempsteven commented 4 years ago

Hmm can I see your file in this directory: ~/plugins/vue-html2pdf.js?

It should look like this:

// vue-html2pdf.js
import Vue from 'vue'
import VueHtml2pdf from 'vue-html2pdf'
Vue.use(VueHtml2pdf)
NanyThery commented 4 years ago

Hi! Thanks for your reply,

Yes, this is what I have in my plugin file:

import Vue from 'vue'
import VueHtml2pdf from 'vue-html2pdf'

Vue.use(VueHtml2pdf)

Also tried with import * as VueHtml2pdf, but no results

image

kempsteven commented 4 years ago

Weird, the error says that the vue-html2pdf component is not registered, but im not seeing anything wrong on your code.

I uploaded the nuxt project I test on try have a look on it: https://github.com/kempsteven/nuxt-tester/tree/main

NanyThery commented 4 years ago

Thank you so much for the time you put into this. I'll give you feedback as soon as I can test it. Thanks again.

NanyThery commented 4 years ago

Hi again!

An update on this. I did the following and even having copied directly your page and component, still, throws me the error of "have you registered the component"?. 1) Copied exactly the same line in nuxt.config plugins. 2) Installed Babel-core, since I noticed you had it in your package and I didn't 3) I copied and pasted your pages/index and also your content-pdf component in my project to test it as is.

Still getting the same error. I am not really sure what it is.

But if it is working in your naked project, there must be something I've installed interfering with the app... I googled a lot but couldn't find anything that puts me in the right direction. I think I've tried all the combinations possible.

I am using Nuxt 2.14, but I don't think it's relevant for the case.

Thank you again for your time.

Kind regards,

Nadine

kempsteven commented 4 years ago

Hello, I'm not exactly sure whats wrong, the main issue is that the component is not registering.

I tried replicating this in a couple of nuxt application types (SSR and JAMStack), still no success in replicating the issue. You could try implementing this in a new nuxt application and compare the two projects and see what could have been the issue.

Good luck!

NanyThery commented 4 years ago

Hello again!

I could finally manage it to work.

1) Component not registered. It seems there was an issue with the packages. Cannot tell which exactly. But it was just ignoring it. So I solved that issue by doing: npm install npm audit fix

On the other hand, and not directly related with this issue:

2) I wanted the pdf download to start as soon as the URL loaded, so I put the generatePDF() function within the mounted() hook. This resulted in an error because the child components were not ready. So I had to implement the $nextTick() function. So, if anyone wants to download a PDF on mounted, yo need to do something like this:

  async fetch() {
    this.activeMenu = this.$store.state.activeMenu
  },
  mounted() {
    this.$nextTick(() => this.print())
  },

  methods: {
    print() {
      this.$refs.html2Pdf.generatePdf()
    },
  },

More doc on this:

What is next Tick

Maybe it could help to put also this use case in the docs for newbies like me. hehe.

Issue solved :D Thanks again for your support.

Regards,

kempsteven commented 4 years ago

Cool :D