Easily Generate PDFs with Node JS and React

Updated on Jan 09,2024

Easily Generate PDFs with Node JS and React

Table of Contents

  1. Introduction
  2. Setting up the Client Side
  3. Creating the HTML Template
  4. Configuring the Server Side
  5. Generating the PDF
  6. Downloading the PDF
  7. Testing the Application
  8. Conclusion

Article

Introduction

Welcome to JavaScript Mastery! In this tutorial, we will learn how to generate dynamic PDFs using HTML code as a template. We will Create a simple receipt that will have dynamic data coming from a React state object. By the end of this tutorial, You will be able to generate and download customized PDFs Based on user input.

1. Setting up the Client Side

To begin, we need to set up the client-side of our application. We will be using Create React App to create a new directory called "client". Open your terminal and navigate to the desired location where you want to create the project. Then, run the following command:

npx create-react-app client

Once the command finishes executing, navigate into the newly created "client" directory by running cd client.

Next, we need to install some dependencies. Run the following command to install Axios and file-saver:

npm install axios file-saver

Axios will be used to make HTTP requests to our server, and file-saver will help us save or download the generated PDFs.

2. Creating the HTML Template

Now that our client side is set up, we can start creating our HTML template for the receipt. In the src folder, open the App.js file and remove the default code. Then, import the necessary dependencies by adding the following lines at the beginning of the file:

import React, { useState } from 'react';
import axios from 'axios';
import { saveAs } from 'file-saver';

Next, we'll set up our initial state. Above the App component, add the following code:

const initialState = {
  name: '',
  receivedID: 0,
  price1: 0,
  price2: 0,
};

This state will hold the values for the name, received ID, and the two prices.

Inside the App component, we'll define our state and create two functions: handleChange and createAndDownloadPDF. Add the following code inside the App component:

const [state, setState] = useState(initialState);

const handleChange = (event) => {
  const { name, value } = event.target;
  setState((prevState) => ({
    ...prevState,
    [name]: value,
  }));
};

const createAndDownloadPDF = () => {
  axios.post('/createPDF', state).then(() => {
    axios.get('/fetchPDF', { responseType: 'blob' }).then((res) => {
      const pdfBlob = new Blob([res.data], { type: 'application/pdf' });
      saveAs(pdfBlob, 'newPDF.pdf');
    });
  });
};

The handleChange function is responsible for updating the state as the user enters data in the input fields. It uses the name attribute of the input field to determine which field to update.

The createAndDownloadPDF function sends a POST request to the /createPDF endpoint, passing the state as the data. This endpoint will generate the PDF based on the received data. Once the PDF is generated, it is fetched from the server using a GET request to the /fetchPDF endpoint. The response data is then converted into a Blob, and the saveAs function from the file-saver Package is used to download the PDF.

3. Configuring the Server Side

Now, let's move on to setting up the server-side of our application. Open a new terminal window and navigate to the root directory of the project. Create a new directory called "server" by running the following commands:

mkdir server
cd server

Inside the "server" directory, create an index.js file by running the command touch index.js.

We first need to install the necessary dependencies for our server. Run the following command:

npm install express body-parser html-pdf

Express is a web application framework for Node.js, body-parser is a Middleware for parsing request bodies, and html-pdf is a module that allows us to convert HTML to PDF.

In the index.js file, import the required dependencies:

const express = require('express');
const bodyParser = require('body-parser');
const pdf = require('html-pdf');

Next, initialize the Express app and set up the server to listen on a specific port:

const app = express();
const port = process.env.PORT || 5000;

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

To enable our app to handle JSON request bodies, add the following middleware before defining the routes:

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

Generating the PDF

We will create a new directory called "documents" inside the "server" directory. This is where we will store our HTML template for generating the PDF. Inside the "documents" directory, create a file named "index.js".

In the "index.js" file, we will export a function that returns the HTML template needed to generate the PDF:

module.exports = () => {
  return `
    <!doctype html>
    <html>
      <head>
        <style>
          /* Add your CSS styles here */
        </style>
      </head>
      <body>
        <!-- Add your HTML structure here -->
      </body>
    </html>
  `;
};

This is a basic template for the receipt. Feel free to customize it according to your needs.

Now, let's go back to the index.js file in the root of the "server" directory. We will create two routes: one for generating the PDF and one for fetching the generated PDF.

First, define the route for generating the PDF by adding the following code:

app.post('/createPDF', (req, res) => {
  const { name, receivedID, price1, price2 } = req.body;

  // Generate the HTML for the PDF using the "index" function from the "documents" directory
  const html = require('./documents/index')({ name, receivedID, price1, price2 });

  const options = {}; // We can add options for the PDF generation if needed

  pdf.create(html, options).toFile('resultPDF.pdf', (err, result) => {
    if (err) return res.status(500).send(err);
    res.send('PDF created successfully');
  });
});

This route receives the data from the client-side and generates the PDF using the HTML template. We pass the received data to the index function from the "documents" directory to generate the dynamic HTML. The PDF is then created using the pdf.create function, and the resulting file is saved as "resultPDF.pdf".

Next, define the route for fetching the generated PDF:

app.get('/fetchPDF', (req, res) => {
  res.sendFile(`${__dirname}/resultPDF.pdf`);
});

Downloading the PDF

Now that we have set up the server, we can test our application by running both the client and server. The client is running on port 3000, and the server is running on port 5000.

To start the client, navigate back to the "client" directory in your terminal and run the command npm start.

To start the server, navigate back to the root directory of the project and run the command node server/index.js.

With both the client and server running, open your browser and go to http://localhost:3000. You should see the client-side of our application.

Enter the required information in the input fields and click on the "Download PDF" button. The server will generate and download the PDF file to your local machine.

Conclusion

In this tutorial, we have learned how to generate dynamic PDFs using JavaScript, React, and Express. We set up the client-side of our application, created an HTML template for the receipt, configured the server to handle the PDF generation, and implemented the functionality to download the generated PDF.

With the knowledge gained from this tutorial, you can now create and download customized PDFs based on user input. This opens up endless possibilities for creating receipts, invoices, reports, and more.

Thank you for reading, and I hope you found this tutorial helpful! Keep exploring and mastering JavaScript for more exciting projects.


Highlights

  • Learn how to generate dynamic PDFs using JavaScript
  • Create customized PDF templates using HTML and CSS
  • Use React for the client-side implementation
  • Utilize Axios for making HTTP requests
  • Save and download the generated PDF using file-saver

FAQ

Q: Can I customize the HTML template for the PDF receipt? A: Yes, you can modify the HTML template according to your specific needs. Just make sure to update the data passed to the template accordingly.

Q: What happens if there is an error during PDF generation? A: If an error occurs during PDF generation, an HTTP response with a 500 status code will be sent back to the client. You can handle this response in your client-side code.

Q: Can I add more fields to the receipt? A: Absolutely! You can add as many fields as you need in the HTML template and update the corresponding state and server-side code to handle the new data.

Q: Are there any limitations on the file size of the generated PDF? A: The file size of the generated PDF can vary depending on the complexity of the HTML template and the amount of data being included. It's best to test with different scenarios to determine any limitations specific to your application and infrastructure.

Most people like