Generate PDF of the current page

I have finally finished a really complex app!! Thanks to UIBakery it took 3 weeks and when I say complex… I mean complex… really long SQL queries feeding data across sets… In the end I am overly impressed with UIBakery and it’s ability to build an app. That said… One of the last steps I am trying to overcome is generating a ‘PDF export’ for all the different pages in my app. I see through the PDF guide about doing tables, but is there a way to do other components or even better yet all the pages in the menu? That would be the ideal case… Any ideas or am I just overlooking something obvious??

Hi @coder911

Nice to know you’ve managed to build a complex app with UI Bakery. Good job! You can share something cool you’ve built in the Showcases section.

Concerning your questions, we do not have the exact guide for printing the whole page as a PDF, however, we once had an example for an image. I’ll share the code below, and you can play around with it to convert it to pdf.

Connect the html2canvas library. You can connect it using on the “Custom Code” tab.
It would convert a visible page to the image with this code (you can trigger it with the “Screenshot” button, for example):

html2canvas(document.body).then(function(canvas) {
    // Create an image from the canvas
    var image = canvas.toDataURL("image/png");
// Create a temporary link element
var downloadLink = document.createElement('a');

// Set the download filename
downloadLink.download = 'screenshot.png';

// Set the link to the image
downloadLink.href = image;

// Trigger the download by simulating a click on the link
document.body.appendChild(downloadLink);
downloadLink.click();

// Clean up: remove the temporary link element
document.body.removeChild(downloadLink);

});

Hope this helps! If you require any further guidance, please let me know.

Cheers!

This is helpful, and I am getting close to a resolution… But I am having an issue…

This prints blank pDF files… I have verified if I don’t use an iframe I get the content as expected… I suspect it is because when I access the hiddenFrame.src I am getting a URL that generates a blank page

My first page name is “Login” and its path is “/login”

In the console.log I am seeing

Processing page 1/21: Login
Navigating /login
Redirecting... COMPLETED

If I try to access that page… it is blank… it is blank even if I manually put the ID of my app in the URL… I am stumped on this one… Can someone help me?

async function printAllPagesToPDF() {
  // Initialize jsPDF
  const { jsPDF } = window.jspdf;
  const pdf = new jsPDF('p', 'mm', 'a4');
  const appPages = {{app.pages}}
  
  // Store current location to return to later
  const currentLocation = window.location.pathname;
  
  // Create a container for temporary navigation
  const hiddenFrame = document.createElement('iframe');
  hiddenFrame.style.position = 'absolute';
  hiddenFrame.style.top = '-9999px';
  hiddenFrame.style.width = '1024px';
  hiddenFrame.style.height = '768px';
  document.body.appendChild(hiddenFrame);
  
  // Process each page
  // for (let i = 0; i < appPages.length; i++) {
  for (let i = 0; i < 2; i++) {
    const page = appPages[i];
    
    // Display progress (optional)
    console.log(`Processing page ${i+1}/${appPages.length}: ${page.title}`);
    
    // Navigate iframe to the page
    console.log(`Navigating ${page.link}`);
    hiddenFrame.src = page.link;
    console.log(`${hiddenFrame.src} COMPLETED`);
    // Wait for page to load
    await new Promise(resolve => {
      hiddenFrame.onload = resolve;
    });
    
    // Wait a bit for any dynamic content to load
    await new Promise(resolve => setTimeout(resolve, 3000));
    console.log(`${hiddenFrame.src} LOADED`);
    // Capture the page content
    const pageContent = hiddenFrame.contentDocument.body;
    console.log(`STILL Processing page ${i+1}/${appPages.length}: ${appPages[i].title}`);    
    // Use html2canvas on the iframe content
    
    const canvas = await html2canvas(pageContent, {
      allowTaint: true,
      useCORS: true,
      scale: 2
    });

    // Add a new page for all but the first page
    if (i > 0) {
      pdf.addPage();
    }
    
    // Increase the iframe size to better capture content
		hiddenFrame.style.width = '1200px';
		hiddenFrame.style.height = '1600px';
    
    // Add page title
    pdf.setFontSize(16);
    pdf.text(appPages[i].title, 20, 20);

    
    // Add the captured image
    const imgData = canvas.toDataURL('image/png');
    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();
    const imgWidth = canvas.width;
    const imgHeight = canvas.height;
    const ratio = Math.min((pageWidth - 40) / imgWidth, (pageHeight - 40) / imgHeight);
    const imgX = (pageWidth - imgWidth * ratio) / 2;
    const imgY = 30;
    
    pdf.addImage(imgData, 'PNG', imgX, imgY, imgWidth * ratio, imgHeight * ratio);
    
  }
  
  // Clean up
  document.body.removeChild(hiddenFrame);
  
  // Return to original page
  window.history.pushState({}, '', currentLocation);
  
  // Save the PDF
  pdf.save('all_pages.pdf');
}

printAllPagesToPDF();

Hi @coder911

JS Step can’t navigate between the pages of the application.
If you need to collect screenshots of all the app pages, you should take a screenshot of one page, save it somewhere (like localStorage or a database), then move to the next page using a Navigate step, and continue like that one by one. In the end, all the screenshots can be stitched together into a single PDF.

Hope this helps,
Kate

Yes this helps… I have rewritten my code to navigate to each page, and I am trying to add them to a unit8array to merge them using pdf-lib to produce one final pdf … everything works except I can’t seem to get pdf-lib to load properly. I know I have to use the UMD to load the external JS library… I have used the link provided from PDF-LIB · Create and modify PDF documents in any JavaScript environment.… But whenever I try to use the libraries PDFDocument functions… I get an error message: “PDFDocument is not defined”

[

UMD Module

](PDF-LIB · Create and modify PDF documents in any JavaScript environment.)

If you aren’t using a package manager, UMD modules are available on the unpkg and jsDelivr CDNs:

Hey!

I was able to connect pdf-lib via:
Custom Code

<script src="https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js"></script>

JS step

async function createPdf() {
    const { PDFDocument, rgb, StandardFonts } = PDFLib;
    const pdfDoc = await PDFDocument.create();
    const page = pdfDoc.addPage([600, 400]);

    const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
    page.drawText('Hello World', {
      x: 50,
      y: 350,
      size: 30,
      font,
      color: rgb(0, 0.53, 0.71),
    });

    const pdfBytes = await pdfDoc.save();

    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'hello.pdf';
    link.click();
  }

  createPdf();

Hope this helps!

Excellent. Thanks!! Worked perfectly apparently I just had the initialization statement using the incorrect syntax… setting it to PDFLib worked for me! Thanks for your help.

For some reason, images do not show up in the export. All my other content appears to work … Any thoughts why images that render fine do not show up in the html2canvas captures??