photo-1535054820380-92c41678b087.png
Cover image for joseph_appsmith

Joseph Petty Verified userVerified user

Sr. Developer Advocate

Appsmith

Exploring Dynamic PDF Generation Methods

Question: How can I generate a PDF from my app? 

Answer: It depends... 

Like most things in programming, there are a ton of ways to generate PDFs from an Appsmith app, or any low-code app or website for that matter. Choosing the right method is about finding a balance between design, functionality, and ease of implementation. This guide will provide an overview of the basic methods, and outline some of the pros and cons to help you select the method that best fits your use case and technical level. 

 

Option 1: Print to PDF from Browser

By far, the easiest option is to just use the browser's print dialog, and select the option to 'Print to PDF'. This will print the entire page of your app, and may not fit correctly on a standard Letter or A4 document size when converting to a PDF, but it can work well if the app's layout is designed with the final print dimensions in mind. 

The browser's print dialog can be opened opened from the File menu, or by clicking cmd+P (Mac) or ctrl+P (Windows). 

NOTE: The print dialog can not be opened by calling window.print() in a JSObject because access to the window object is blocked for security. 

Option 2: Iframe or Custom Widget

The main issue with Option 1 is that the source is not a fixed size like a PDF. The app adjusts for different screen sizes, but when printing to a fixed size things can get cut off or have excessive margins. To address this, you can create your own layout using HTML and apply a fixed width using CSS, then print from within this iframe or custom widget, instead of from the parent window (Appsmith). This option is fairly easy to set up, but making it look good will require some frontend experience. 

Let's look at a basic example with the following customer data: 

order : {
    id: 12345,
    customer_name: "Joseph",
    total: 21.95
}

This data can be merged with a template literal to add the PDF template and a few HTML tags. 

email template merge js

Then, add an iframe to display the output of the mergeTemplate() function. 

Printing from an Iframe

Inside an iframe or custom widget, the window object is no longer blocked because it's scoped to only that one component. So you can call window.print() from inside your iframe or custom widget. 

print button html

You can also add some CSS to hide the button when printing, and to style the document. 

<button onclick="window.print()">print</button>

      <p>Hi Joseph,</p>
      <p>Thank you for your order!</p>
      <p>Please see details below:</p>
      <p><strong>OrderID:</strong> 12345</p>
      <p><strong>Total:</strong> $21.95</p>
      <p>We appreciate your business!</p>
<style>
body{
font-family: sans-serif
}
@media print {
          button {
            display: none;
          }
        }
</style>

Option 3: JSPDF

The next option is to use the JSPDF library to build a PDF file directly, instead of writing HTML. JSPDF is one of the recommended libraries when you open the custom library pane. Just click the download button to install it and start using it in a JSObject. 

jspdf install

 

Once installed, you can build a PDF by adding text, formatting, and changing other options using the methods provided by the JSPDF library. 

Here's a snippet to produce a PDF as a dataurl that can be viewed in the Document Viewer widget:

export default {

  order: {
    id: 12345,
    customer_name: "Joseph",
    total: 21.95
  },

  buildPDF(orderData = this.order) {
    const pdf = jspdf.jsPDF();
    pdf.setFont("times");
    pdf.setTextColor("#e15614");
    pdf.text(`Hi ${orderData.customer_name},`, 10, 10);
    pdf.text("Thank you for your order!", 10, 20);
    pdf.text("Please see details below:", 10, 30);
    pdf.text(`OrderID: ${orderData.id}`, 10, 40);
    pdf.text(`Total: $${orderData.total}`, 10, 50);
    pdf.text("We appreciate your business!", 10, 60);
    return pdf.output("dataurlstring");
  }
}

For a more detailed walkthrough of using JSPDF, check out this video:

Building A Data Driven PDF Generator With The JSPDF Library

Option 4: PDF Template APIs

If you want a more visual approach to designing PDFs instead of code-based, there are several templating services with APIs. These allow you to design templates and add styling like you would with a Word document. Then you can send an API request with your data, and the service will return the PDF with the data merged in. This approach makes it easier to design great looking PDFs without coding, but it may come with subscription fees and/or require self-hosting your own platform just for generating PDFs. 

One option is APITemplate.io. It's free for up to 50 PDFs a month. 

How To Generate PDF Reports With Apitemplate.io

Another option is Carbone.io, which is open-source and offers 100 PDFs per month on the free plan. 

How To Generate PDF Reports With Carbone.io

There are several other options, so shop around and find the one that works best with your feature requirements and budget. 

Option 5: Other PDF Libraries

Other PDF generation libraries like HTML2PDF, PDFKit, and HTML2Canvas all require access to the DOM and/or window object, and therefore will not work in a JSObject. However, these libraries can be used in a custom widget! By combining the HTML template approach from Option 2, you can build the PDF in a custom widget, then use one of these libraries to convert the HTML to a PDF. 

Conclusion

There are lots of options when it comes to Generating PDFs in Appsmith, ranging from quick and easy, to more complex and feature-rich solutions. To choose the right option, it helps to be familiar with the available methods and the pros and cons of each. 


 


 

pchambless1 public View pchambless1's profile
Mon, 07/08/2024 - 17:14

One of these days I gotta jump on to the JSPDF library.  I'm making most of my reports, and it's quite a few, in Custom Widgets.    Thanks, Joseph!