I have a working solution for Nuxtv3 (with server-side rendering). After trying a bunch of different vue-specific packages, including vue-html2pdf
, I realized that most of them have been written for Vue2.
Instead, I chose to use html2pdf
directly.
Upon directly importing html2pdf
in the component where I need to add the functionality for converting html to pdf, Nuxt throws the following error: ReferenceError: self is not defined
. This essentially happens because the line where the library is being imported runs on the server side as well and when it is imported, it tries to access a variable that isn't defined on the server side.
My solution was to create a custom plugin that runs only on the client side. It is very simple to do this in Nuxtv3 by just ending the filename with .client.ts
as opposed to just .ts
. Here is what plugins/html2pdf.client.ts
looks like:
import html2pdf from 'html2pdf.js'
export default defineNuxtPlugin(() => {
// had to make a plugin because directly importing html2pdf.js in the component
// where I need to use it was causing an error as the import would run on the server
// side and html2pdf.js is a client-side-only library. This plugin runs on the
// client side only (due to the .client extension) so it works fine.
return {
provide: {
html2pdf: (element, options) => {
return html2pdf(element, options)
}
}
}
})
Now, I can safely use it in my component as:
const { $html2pdf } = useNuxtApp()
function downloadPDF() {
if (document) {
const element = document.getElementById('html2pdf')
// clone the element: https://stackoverflow.com/questions/60557116/html2pdf-wont-print-hidden-div-after-unhiding-it/60558415#60558415
const clonedElement = element.cloneNode(true) as HTMLElement
clonedElement.classList.remove('hidden')
clonedElement.classList.add('block')
// need to append to the document, otherwise the downloading doesn't start
document.body.appendChild(clonedElement)
// https://www.npmjs.com/package/html2pdf.js/v/0.9.0#options
$html2pdf(clonedElement, {
filename: 'filename.pdf',
image: { type: 'png' },
enableLinks: true
})
clonedElement.remove()
}
}
Basic usage of html2pdf
: https://www.npmjs.com/package/html2pdf.js/v/0.9.0#usage
Configuration for html2pdf
: https://www.npmjs.com/package/html2pdf.js/v/0.9.0#options