DEV Community

Cover image for How to Generate PDF from html in React Native
Md. Jamal Uddin
Md. Jamal Uddin

Posted on

How to Generate PDF from html in React Native

Introduction

Generating PDF based on different transaction is an important part of any retail applications. today we are going to show how can we generate PDF documents in React Native.

React Native has several good NPM libraries to generate PDF but articles and blogs are very few. So, I am letting you know how can you generate PDF in React Native using the very popular React Native PDF generation library called react-native-html-to-pdf.

Create a React Native Project

npx react-native init MyRNPDF --template react-native-template-typescript
Enter fullscreen mode Exit fullscreen mode

this command will create a new react native project

Folder Structure of a Newly created React Native Project

Folder Structure of a React Native Project

Change App.tsx file to print Hello World!

// App.tsx
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';

function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Hello World</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#aac',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 30,
    color: '#fff',
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

Build the Project and Run on an Emulator

npm run android
Enter fullscreen mode Exit fullscreen mode

after successful build of the project you will see a Hello World! message on your emulator/device screen:

Output of Emulator Screen

Add Dependency Library for PDF generation

npm i react-native-html-to-pdf
Enter fullscreen mode Exit fullscreen mode

we are using TypeScript in our project. So, we have to install below package too for type definition of react-native-html-to-pdf library.

npm i @types/react-native-html-to-pdf
Enter fullscreen mode Exit fullscreen mode

iOS only recommendation

React Native version >= 0.60.0, they have introduced autolinking so we do not required to link the library but need to install pods. but only for iOS we need install dependencies via pod's:

cd ios && pod install && cd ..
Enter fullscreen mode Exit fullscreen mode

Edit the File Path

Go directly to the source code in your

  • node modules
    • react-native-html-to-pdf
    • android
      • src
      • main
        • java
        • com
          • christopherdro
          • htmltopdf

In the convert() function change this code block:

File path = (Environment.MEDIA_MOUNTED.equals(state)) ?
          new File(mReactContext.getExternalFilesDir(null), options.getString(DIRECTORY)) :
          new File(mReactContext.getFilesDir(), options.getString(DIRECTORY));
Enter fullscreen mode Exit fullscreen mode

existing code block

with below code block:

File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), options.getString(DIRECTORY));
Enter fullscreen mode Exit fullscreen mode

replaced code blocks

And that should change the file path to the appropriate location inside your emulator/device.

Permission for Android

We are accessing external storage so we need to add two permission in AndroidManifest.xml file.

We are going to add the following permissions in the AndroidManifest.xml

  • default AndroidManifest.xml file:

default AndroidManifest.xml file

  • Permission Code Block:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Enter fullscreen mode Exit fullscreen mode

Changed AndroidManifest.xml file

Setting PDF generation

Update App.tsx file as per your need with settings of react-native-html-to-pdf library:

import React, {useState} from 'react';
import {Alert, Pressable, StyleSheet, Text, View} from 'react-native';
import RNHTMLtoPDF from 'react-native-html-to-pdf';

function App() {
  const [isLoading, setIsLoading] = useState(false);
  const [count, setCount] = useState(1);

  const orderLines = [
    {
      id: 1,
      product: 'Product 1',
      quantity: 1,
      price: '$10.00',
    },
    {
      id: 2,
      product: 'Product 2',
      quantity: 2,
      price: '$20.00',
    },
    {
      id: 3,
      product: 'Product 3',
      quantity: 3,
      price: '$30.00',
    },
  ];

  const generatePDF = async () => {
    setIsLoading(true);
    try {
      const html = `
        <html>
          <head>
            <style>
              body {
                font-family: 'Helvetica';
                font-size: 12px;
              }
              header, footer {
                height: 50px;
                background-color: #fff;
                color: #000;
                display: flex;
                justify-content: center;
                padding: 0 20px;
              }
              table {
                width: 100%;
                border-collapse: collapse;
              }
              th, td {
                border: 1px solid #000;
                padding: 5px;
              }
              th {
                background-color: #ccc;
              }
            </style>
          </head>
          <body>
            <header>
              <h1>Invoice for Order #${count}</h1>
            </header>
            <h1>Order Details</h1>
            <table>
              <tr>
                <th>Order ID</th>
                <td>${count}</td> 
              </tr>
              <tr>
                <th>Order Date</th>
                <td>29-Jul-2022</td>
              </tr>
              <tr>
                <th>Order Status</th>
                <td>Completed</td>
              </tr>
              <tr>
                <th>Order Total</th>
                <td>$13232</td>
              </tr>
            </table>
            <h1>Order Lines</h1>
            <table>
              <tr>
                <th>Product ID</th>
                <th>Product Name</th>
                <th>Product Qty</th>
                <th>Product Price</th>
              </tr>
              ${orderLines
                .map(
                  line => `
                <tr>
                  <td>${line.id}</td>
                  <td>${line.product}</td>
                  <td>${line.quantity}</td>
                  <td>${line.price}</td>
                </tr>
              `,
                )
                .join('')}
            </table>
            <footer>
              <p>Thank you for your business!</p>
            </footer>
          </body>
        </html>
      `;
      const options = {
        html,
        fileName: `invoice_${count}`,
        directory: 'Invoices',
      };
      const file = await RNHTMLtoPDF.convert(options);
      Alert.alert('Success', `PDF saved to ${file.filePath}`);
      setCount(count + 1);
      setIsLoading(false);
    } catch (error: any) {
      Alert.alert('Error', error.message);
    }
  };

  if (isLoading) {
    return <Text>Generating PDF...</Text>;
  }

  return (
    <View style={styles.container}>
      <Pressable style={styles.button} onPress={() => generatePDF()}>
        <Text style={styles.text}>Generate PDF</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#aac',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 24,
    color: '#fff',
  },
  button: {
    backgroundColor: '#6c8ee3',
    padding: 15,
    borderRadius: 10,
    margin: 20,
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

build your project again:

npm run android
Enter fullscreen mode Exit fullscreen mode

Output

  • First look of our App:
    Image description

  • Click the Button to generate PDF file and you'll see an Alert:

PDF Success Message

Visit the location which is showing in Success Alert and see generated PDF file.

  • On Emulator:

Generated PDF File Location

On your real device you can see the file on your external device folder:

  1. Generate PDF on Real Device:

PDF Generation on Real Device

  1. Locate the generated PDF file:

Locate PDF File from external storage

Resources

Credit

Top comments (3)

Collapse
 
dad_hai_6e6a41079dc756a57 profile image
frontend developer

can you please tell for android how will we save this file in download

Collapse
 
jaamaalxyz profile image
Md. Jamal Uddin

change the below code block to set your desired location:

File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), options.getString(DIRECTORY));
Enter fullscreen mode Exit fullscreen mode

Here I have chosen the Documents directory by Environment.DIRECTORY_DOCUMENTS

Collapse
 
mansilaad profile image
Mansi Laad
  1. Can we change the default path of file where it is going to download...?
  2. Unable to find the file on IOS...