1

I appreciate you looking. Here's the problem I'm having:

  1. I have a project that includes pdfjs as a static resource. Part of this resource is an html file, viewer.html, that is the actual pdf viewer. This is unmodified, save for #2.
  2. The html file is modifed with an event listener so I can pass it data via postMessage.
  <script>
    if (window.addEventListener) {
      // For standards-compliant web browsers
      window.addEventListener("message", handleMessage, false);
    } else {
      window.attachEvent("onmessage", handleMessage);
    }

    function handleMessage(evt){
      ...
    }
  </script>
  1. I have an LWC that is simply an iframe where the iframe src is viewer.html
<template>
    <div>
       <iframe src={viewerUrl} style={viewerStyling}></iframe>
    </div>
</template>
get viewerUrl() {
  return PDFJS + "/web/viewer.html";
}
  1. The LWC retrieves data via Apex controller, processess it, and then passes the data to the iframe via postMessage. Viewer.html receieves the data and loads the file.
  loadData() {
    let data = {
      pdfData: this.pdfData,
      ...
    };

    this.template.querySelector("iframe").contentWindow.postMessage(data, "domain.name");
  }

The iframe LWC is the child of a larger component. Before I continue, I want to say that everything is working well. I'm seeing issues when the components are initially loaded.

I was seeing an issue when the components are initially loaded where a documents are loaded intermittently and I traced it down to when the event listener is registered in viewer.html.

Good load:

...
other child: renderedCallback

viewer.html: load
viewer.html: addEventListener

pdfjs child: loadData

viewer.html: handleMessage
...

Bad load:

...
other child: renderedCallback

pdfjs child: loadData

viewer.html: load
viewer.html: addEventListener
...

For those that failed the listener is registered AFTER I've retreived the data and attempted to post it to the iframe. Since there's no listener registered yet in viewer.html postMessage just silently fails.

My guess is that this is related to when the iframe is loaded into the DOM (I could be very wrong, though). My question, is there a way to force-load the iframe without doing it manually? Ultimately I need the html file's event listener to be loaded and ready for me when I need it.

I apologize in advance if this is a super-easy fix (which I hope it is), but my trick bag is empty and I'm not sure what to do.

Thanks for any an all help

1
2

This is a timing issue, depending on when you are calling loadData() in your LWC and the Apex time to return the data, the iFrame may or may have not registered the listener yet.

An easy solution would be to just load the data after the iFrame finished loading:

<template>
    <div>
       <iframe src={viewerUrl} style={viewerStyling} onload={loadData}></iframe>
    </div>
</template>

For reference, here is the MDN onload event:

Notes

The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.

1
  • Thanks @gale-force-wizard, I'll give you the points because you pointed me in the right direction. I had onload in place originally but had taken it out at some point. This was one bug fixed :) There were other bugs, too, but ultimately the issues I had were due to async callback timing and your response helped to keep me on track with those. Apr 16 '21 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.