Disclaimer: for this particular problem, there is a much simpler solution than that oulined here (see way below). Regardless, I’m documenting the complicated solution, because it will certainly become useful again in the future.
I’m working on a web application that archives typeset documents and images. Once a document is archived, users are able to view an HTML conversion of the document through the browser without having to copy the original file to their local machines. The main application window has a paginated list of archived documents. The user selects the document he wants to view and it opens in a new browser tab.
The root component on the main application tab opens a new tab in a manner similar to this:
page.html provides the scaffolding for the HTML representation of a PDF, DOC, or some other typeset document. In conventional React style, the root component is rendered to an element of your choosing. In this case, the element looks like this:
Here’s the problem: the main application window either needs to
- download the HTML representation of the requested archived document, or
- obtain the mongo ID of the archived document so that it can be downloaded when
page.htmlrenders the root component
Either way, the problem is the same. I couldn’t set the page content or document ID until after
page.html was loaded. For illustrative simplicity, suppose I proceed by obtaining the mongo ID. In this case, I need
page.html to look like this after it’s loaded:
page.html is fully loaded, a gebo-server-style request is sent to the archiver-agent:
These lines set
#page‘s attribute in page.html:
But wait! That’s great and all, but how do I tell the root React component to wait until the
docId attribute has been set?
Behold the MutationObserver!
This code was appended to the root component’s definition, which is rendered in
page.html. It’s adapted from the example provided on the Mozilla page.
This code simply waits until the
#page element’s attributes change before rendering the root component in
You’ll have to take my word for it, but there were very good reasons why I initially pursued this complex solution. The way things worked out, however, allowed me to simply render the root component in
page.html from the application loaded in the main window like this:
Obviously, this is a much cleaner solution than the one outlined above. Nonetheless, I know that which has been documented will become useful to me again in the future.