This uses jsPDF and not html2pdf. I could never get pagination working with html2pdf. jsPDF has pretty rudimentary pagination (it will only prevent page breaks within text), but hey, at least that much actually works!
This might be a little rough around the edges, buyer beware!
Since both Retool and Handlebars.js use curly braces {{ }} this causes a conflict. So your Handlebars templates will use double square brackets instead [[ ]] and the component translates these for use by Handlebars.
You cannot use image URLs in your templates. There are CORS issues with this that I don't think are avoidable (I spent many hours trying!). So you need to convert your images to base64 and use those. My sample app shows how to pass an image in the JSON data using base64. Here is a site that will do the conversions: https://www.base64-image.de/
This is hard coded for A4 in portrait and px units. jsPDF get a little squirrely when going to inch units so I kept it metric-ish which seems to work (I did say it was a little rough around the edges didn't I?)
I included a couple of helpers. currency converts a numeric value into US dollars (sorry Europe!). sumTotal sums an array with a total property and returns it in dollars. sumQuantity sums an array with a quantity property. You can see how these work in the sample app.
The module consists of three components:
A PDF Viewer that does nothing but display the base64 passed to it.
A custom component that does all of the magic. Study this to see how things work, change margins, page orientation, modify handlebars helpers and such.
A Refresh button. This is needed because if you change the JSON or template the PDF will not be automatically redrawn.
Improvements that someone could work on if they so desired:
Direct printing without download.
Add Inputs for page orientation, page size, margins, canvas scaling and such things.
A way to pass in Handlbars helpers (not sure if this is possible but would make it more easily extensible)
Explore possibly using pdfMake instead of jsPDF. pdfMake talks a good game, but it is v0.2 and I ran out of steam to see if it is a better alternative to html2pdf and jsPdf.
Hmm... Both my S3 and Azure storage claim to be set up for CORS and neither works for me. Apparently I did not sacrifice the right animal to the CORS Gods. ?
@bradlymathews Seriously amazing work! Something like this really should be available out of the box by Retool.
One thing I changed was removing the top bar of the pdf component and manually creating a download button so that I could manipulate the pdf name. If anyone has found a better way to do this, let me know!
The download pdf syntax looks like this if anyone is interested.
It should automatically split into multiple pages.
The jsPDF docs can tell you more about its pagination capability, which is pretty rudimentary. Other libraries claim to have better pagination, but it never actually works for me.
hi @bradlymathews this is the only way to use jspdf in retool? i cant use it like external library? how i can install those files you sent in post? i need two json?
That is the only way I know of to use jsPDF in Retool. You may be able to do all of this within a JS query, using jsPDF as an external library, but that has not yet been publicly tried for any of the PDF libraries. Feel free to try it and let us know!
You do not need to install the files, they are just referenced from an external source within the Custom Component.
I have not looked at the component in a while so I am not sure which two JSON's you are referring to, but I made this an minimal as I could, so it needs everything that is there.
i see several json files, hope retool can have a free option and easier to integrate jspdf the services like carbone documint are expensive (i need it without watermark)
That link changed on me! I swear it worked before.
I edited the original post with the correct link. If you could do me a favor and edit your post to remove the bad link which was copied, that would be appreciated.
i believe what you've suggested is the solution i have been trying to accomplish, but would you be willing to share some screenshots to get started for us super-newbies?
i appreciate all your help in this community, @bradlymathews, i've seen a lot of your posts and am learning a ton