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??