Download HTML as a PDF in React
Downloading PDF is a common use case in modern front-end applications. But building PDF on the client side can be painful. In React we have some awesome libraries like react-pdf/renderer to help us.
Problems With the Traditional Libraries
react-pdf/renderer
is an awesome library and provides lots of customization. but it comes with its own cost. For example
You have to design a separate component for your PDF document
Sometimes the rendering fails if you don’t handle edge-cases properly
You have to style separately and according to their specification.
All of these are okay if you want to build a data-heavy and customized PDF. But what if you want something simpler? > What if you just want to print the component that is being rendered as it is?
Let’s see how we can download any component as a PDF using a neat trick and some JavaScript knowledge.
Overview
The process that we are going to follow is converting the HTML element into an image and then putting the image into another powerful PDF library. > HTML document -> Image -> PDF
For this, we need two libraries.
html2canvas -> will convert our HTML document to image
jspdf -> will insert the generated image into a PDF file
The fullomplete code is at the bottom. If you are interested only in that go there directly. Otherwise bear with me. It won’t take long
Step 1. Install Dependencies
First, install the required dependencies.
yarn add jspdf html2canvas
STEP 2: Add The Downloader Function
Now Either create a separate component for your GenericPdfdownloader
or put the following code inside the component you want to download.
const downloadPdfDocument = (rootElementId) => {
const input = document.getElementById(rootElementId);
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.save("download.pdf");
})
}
What the code is doing
Input
-> This function takesrootElementId
as input. This will be the id of the downloadable component. We can define the id of any element like the following
return <div id="divToDownload">
// YOUR OTHER COMPONENT CODE GOES HERE
</div>
So if we want to download the component inside the div
with the id=”divToDownload”
then we have to pass ”divToDownload”
into the function
1. Getting the HTML Element
In the next step, we are getting the HTML element with the passed Id.
const input = document.getElementById(rootElementId);
2. Converting HTML to Image
Next, we pass the element into the html2canvas
which gives us back an image
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
})
3. Putting The Image into PDF
Next, we create a new PDF document and put the image inside that.
const pdf = new jsPDF();
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.save("download.pdf");
Here the two zeroes are padding
for the generated PDF document. You can change them as you want.
Also, you can modify the downloadable file name.
Complete code
Here is the full code for a custom PDF downloader which takes two arguments:
The root elements id as
rootElementId
Download filename
downloadFileName
import React from 'react';
import html2canvas from "html2canvas";
import { jsPDF } from "jspdf";
const GenericPdfDownloader = ({rootElementId , downloadFileName}) => {
const downloadPdfDocument = () => {
const input = document.getElementById(rootElementId);
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.save(`${downloadFileName}.pdf`);
})
}
return <button onClick={downloadPdfDocument}>Download Pdf</button>
}
export default GenericPdfDownloader;
Now you can just place this component anywhere in your project like the following:
import React from'react';
import GenericPdfDownloader from "./views/GenericPdfDownloader";
function App() {
return (
<>
<GenericPdfDownloader
downloadFileName="CustomPdf"
rootElementId="testId"
/>
<div id="testId">
This is A Downloadable Component
</div>
</>
);
}
export default App;
Conclusion
There you go! Now you have your custom PDF downloader that can be used anywhere in your project. Thank you for reading!
Have something to say?
Get in touch with me via LinkedIn