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.

  1. html2canvas -> will convert our HTML document to image

  2. 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 takes rootElementId 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:

  1. The root elements id as rootElementId

  2. 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


Share this post


Read more articles...

team

Upload files to Google Cloud Storage from React

team

How to Upload Files to AWS S3 in React

team

Aws Lambda that Reacts to S3 File Upload

team

How to Build an NPM package for React

team

How to Use AWS S3 in NodeJS

Profile Image

Who I am

Hi, I amMohammad Faisal, A full-stack software engineer @Cruise , working remotely from a small but beautiful country named Bangladesh.

I am most experienced inReactJS,NodeJS andAWS

Buy Me a Coffee Widget