Preview a Dynamic Content region as a PDF in your Oracle APEX application
Table of contents
Introduction
Including Dynamic content regions in an Oracle APEX application has sort of become a common practice by most developers due to its ability to render any HTML or text using the PL/SQL Web Toolkit. There are several use cases such as displaying a summary of responses, purchase orders, invoices and lots more. However, there could be an additional user requirement to have them previewed as PDFs. This post shows you how I achieved this using jsPDF - a javascript library for generating PDFs.
demo: Dynamic content to PDF
My Approach
I have achieved this using the steps below:
Add the following URLs to the page property
Javascript (File URLs):
https://html2canvas.hertzen.com/dist/html2canvas.min.js https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js https://unpkg.com/dompurify@3.0.5/dist/purify.js
Function and Global Variable Declaration:
async function printPDF(pElement) {
var pdf = new jspdf.jsPDF({format: "a4", unit: "mm"});
pdf.html(pElement, {
callback: function (pdf) {
const fileInput = document.getElementById('PXX_BLOB_HOLDER');
var file = new File([pdf.output('blob')], 'pdfpreview.pdf');
let container = new DataTransfer();
container.items.add(file);
fileInput.files = container.files
apex.page.submit( {
request: "SUBMITREQ",
showWait: true,
} );
},
margin: 10,
width: 190,
windowWidth: 950,
autoPaging: 'text',
});
}
Create a region 'File Browse region' and set Appearance - Template: Inline Dialog
Add a file browse item type such as PXX_BLOB_HOLDER (where XX is the page number) and set below
Create a Dynamic content region 'Dynamic content' and include the below code in the PL/SQL Function Body returning a CLOB section.
PL/SQL:
declare
l_clob clob;
cursor c_random is
select employee_id, first_name,last_name,phone_number
from employees
where rownum <= 40;
begin
l_clob :='<div id="genpdf">';
for a in c_random
loop
l_clob:=l_clob||apex_escape.html(a.employee_id) || ' '||apex_escape.html(a.first_name)||' '||apex_escape.html(a.last_name) || ' ('||apex_escape.html(a.phone_number)||')<br/>' ;
end loop;
l_clob:=l_clob||'</div>';
return l_clob;
end;
Create a button 'PDF_Preview' in the Dynamic content region. This button will generate the PDF on the client side.
Add a when button click Dynamic action to the button 'genpdf' as shown below:
Execute Server-side Code
PL/SQL:
delete from apex_application_temp_files;
Execute JavaScript Code
*Note: Please ensure the id names in the dynamic content region and the javascript code below match.
JavaScript:
var element = document.getElementById('genpdf');
printPDF(element)
Create an AJAX callback: Run this application process when requested by a page process and call it 'pdf_preview'.
PL/SQL:
declare
l_blob_content blob;
l_mime_type VARCHAR2(200);
l_file_name VARCHAR2(200):='pdfpreview.pdf';
l_sla_id NUMBER;
l_err_code VARCHAR2(1000);
l_err_msg VARCHAR2(1000);
v_sqlerrm VARCHAR2(1000);
BEGIN
SELECT blob_content,
mime_type
INTO l_blob_content,
l_mime_type
FROM apex_application_temp_files;
sys.HTP.init;
sys.OWA_UTIL.mime_header(l_mime_type, FALSE);
sys.HTP.p('Content-Length: ' || DBMS_LOB.getlength(l_blob_content));
sys.HTP.p('Content-Disposition: filename="' || l_file_name || '"');
sys.OWA_UTIL.http_header_close;
sys.WPG_DOCLOAD.download_file(l_blob_content);
apex_application.stop_apex_engine;
EXCEPTION
WHEN apex_application.e_stop_apex_engine
THEN RAISE;
WHEN OTHERS THEN
HTP.p('Kindly generate the document');
END;
Create a static region to display the PDF in an iframe
JavaScript:
<p align="center">
<iframe src="f?p=&APP_ID.:0:&SESSION.:APPLICATION_PROCESS=pdf_preview:NO::" width="99%" height="700">
</iframe>
</p>
Conclusion
This approach is entirely on the client side and you may choose to download and/or print the document. I hope you find it useful.