iframe-printer
Reactive icon

IFrame Printer

Stable version 1.0.0 (Compatible with OutSystems 11)
Uploaded
 on 17 October 2021
 by 
0.0
 (0 ratings)
iframe-printer

IFrame Printer

Documentation
1.0.0
Features
2 public reusable WebBlocks:

- WB_ComponentMount: WebBlock to be placed inside the list, in the RWA page to be printed.
It should be rendered right after the last item of the list is visible, i.e. in the True branch of a condition which checks if the last item of the list is reached.
This posts a 'component mounted' message for the consumer (via window.top.postMessage) to understand that the list is fully rendered and ready to be sent to print dialog.


- WB_ReactiveIframePrinter: WebBlock with iFrame, to be placed where user starts the print request (where the URL-to-be-printed will be supplied).
URL of the reactive web page will be assigned as the source of iFrame and when it's fully loaded, the content will be passed to print dialog.


- A popup that serves as a loading overlay is shown once the URLToPrint parameter is passed to WB_ReactiveIframePrinter from the consumer and the iFrame is started to be loaded. The overlay will be displayed until the printable content is fully rendered in the iFrame, then it will be closed and browser print dialog will be opened.


- The Image, Text and CancelActionLabel can be configured in the consumer as these are placeholders in the producer.


- The dependency to OutSystems UI is solely for the progress bar display option.



Under the hood
Normally for TWA (Traditional Web Application) pages, this could be done by loading the printable into a hidden iFrame and wait for it to be fully rendered, and after that the JS function to open the print dialog would be triggered. This could be done by using JS onload event, and we would call the print function in that iframe.onload.

- This approach doesn’t work with RWA pages, as they work with async calls and the real "render finish" of the page is not detectable by the iframe.onload event.

- So instead of the iframe.onload event, we use the "componentDidMount" JS event approach.

- This method works well if we can check if the last item that needs to be loaded on the page is known to us (e.g. a list with many items).


- We check whether the last item of the list is loaded or not by rendering a container after the last item of the list. Condition to check is:

Records.List.CurrentRowNumber = Records.List.Length - 1


- And in the ComponentDidMount handler, we “post a message” as in the JS code in screenshot.

This is to understand if loading of the page is finished; so there is a counterpart "window.onmessage" in the other screen (where this printable is loaded into an iframe) to catch this message.


- In the other screen with the iFrame, after we assign the URL of the printable to the src of the iFrame, we check if the same message ('iframe-loaded') is received or not; if received, we send the content of the iframe to print dialog:

This is how the app understands that the content of the iFrame is fully loaded and ready for the subsequent work.




Note: This approach works well with RWA pages with lists; to understand if e.g. the images in the page are loaded or not, it might not be enough as images are loaded async as well.


See this forum entry for the applied solution.