There are plenty of custom solutions, as well as libraries to help you generate PDF from HTML. eKoopman’s html2pdf.js has been here for a while and is often the top choice of most developers. However, React, Vue and Angular have some enhanced versions of the same library. The problems with html2pdf.js has always been related to paddings and margins between lines. When printing some content to PDF, leading to multiple pages / pagination with improper spacing. vue-html2pdf seems to have resolved that issue. It also added plenty of bells and whistles on top of it. Let me show you how to use vue-html2pdf here:
Project setup
In your Vue project, install vue-html2pdf using npm:
npm install vue-html2pdf --save
With that being done, create a template (as a component) where you want to keep your printable content. I’m naming this file ContentToPrint.vue:
<template>
<div style="margin: 12px 12px">
<img src="https://picsum.photos/500/300" />
<div>
<p>
<strong
><a href="http://nightprogrammer.com/" target="_blank"
>Nightprogrammer.com</a
></strong
>: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
posuere, tellus lobortis posuere tempor, elit sem varius libero, ac
vulputate ante orci vel odio. Nam sit amet tortor malesuada tellus
rutrum varius vel a mauris. Integer volutpat neque mauris, vel imperdiet
mi aliquet ac. Proin sed iaculis ipsum. Vivamus tincidunt egestas
sapien, vitae faucibus velit ultricies eget. Donec mattis ante arcu, a
pretium tortor scelerisque et. Morbi sed dui tempor, consectetur turpis
sed, tristique arcu.
</p>
<p>
Quisque nec ante faucibus, lobortis neque eget, placerat massa. Mauris
tincidunt ante faucibus dui semper eleifend. Morbi sit amet velit lacus.
Maecenas suscipit pulvinar lacus, ac feugiat erat venenatis porta. Donec
at turpis ultrices, vehicula justo eu, laoreet magna. Ut consequat
eleifend posuere. Quisque nec ante faucibus, lobortis neque eget,
placerat massa. Mauris tincidunt ante faucibus dui semper eleifend.
Morbi sit amet velit lacus. Maecenas suscipit pulvinar lacus, ac feugiat
erat venenatis porta. Donec at turpis ultrices, vehicula justo eu,
laoreet magna.
</p>
</div>
</div>
</template>
export default {}
Code language: HTML, XML (xml)
After that, create a component that will trigger the PDF generation functionality, here I’m doing it in App.vue for the demo purpose:
<template>
<div id="app">
<div @click="generatePDF()" class="np-btn">Generate PDF</div>
<vue-html2pdf
:show-layout="false"
:float-layout="true"
:enable-download="true"
:preview-modal="true"
:paginate-elements-by-height="1400"
filename="nightprogrammerpdf"
:pdf-quality="2"
:manual-pagination="false"
pdf-format="a4"
:pdf-margin="10"
pdf-orientation="portrait"
pdf-content-width="800px"
@progress="onProgress($event)"
ref="html2Pdf"
>
<section slot="pdf-content">
<ContentToPrint />
</section>
</vue-html2pdf>
<div>
<ContentToPrint />
</div>
</div>
</template>
<script>
import VueHtml2pdf from "vue-html2pdf";
import ContentToPrint from "./ContentToPrint";
export default {
name: "App",
methods: {
onProgress(event) {
console.log(`Processed: ${event} / 100`);
},
hasGenerated() {
alert("PDF generated successfully!");
},
generatePDF() {
this.$refs.html2Pdf.generatePdf();
},
},
components: {
VueHtml2pdf,
ContentToPrint,
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.np-btn {
padding: 2px 8px;
margin: 12px 8px;
border: 1px solid #da1010;
width: 110px;
background: #da1010;
border-radius: 6px;
color: #ffffff;
cursor: pointer;
}
</style>
Code language: HTML, XML (xml)
Let me explain what I’ve just done by lines:
3: generatePDF() is called when you hit the Generate PDF button
45: This generates the PDF file with the passed props
5: This is the component which will generate the PDF with the passed props. Most of the prop names are self explanatory. However it’s worth noticing that :pdf-quality ranges from 0-2. 2 being the highest quality and 0 being the lowest. 0 will actually make the PDF empty.
You’d also notice that I’ve imported the ContentToPrint.vue component and rendered it at two places: Line 22 and 26. 22 is to place the actually PDF content which the generator will generate. 26 to show it to the web user how the PDF is going to look like. Alternatively, you can change :show-layout to true. This will serve the same purpose, but on an overlay.
This is how the web view should look like:
And here’s a printed PDF view:
Ah, and don’t worry about the different images you see here. I’ve using a random image generator which generates a new image every time.
You can find the source code and demos from my repos here:
Codesandbox | Demo | Github
this generates blank pdf for me:
hii
Function:
generatePDF() {
this.$refs.html2Pdf.generatePdf();
},
Hi Joyal, make sure you’re including the ref inside the component as ref=”html2Pdf”. Also, the element it targets should have some positive clientHeight for it to work.
Thanks so much! worked like charm
Thanks for the article. Exactly what I needed.