6

Im migrating a lightning component that has a VF iframe that is using the postMessage function

When I try to use the same function in LWC I get a the following error:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://dev123.lightning.force.com') does not match the recipient window's origin ('https://dev123.visualforce.com').

tried a couple ways with the same result

Here is my lwc code

html

<template>
<lightning-button onclick={sendData}></lightning-button>
<iframe id="vfFrame" src={vfHost} height="100%" width="100%"> . 
</iframe>
</template>

js

import { LightningElement, api} from 'lwc';


export default class orderBooks extends LightningElement { 
@api books = [];

vfHost = 'https://velocity-energy-3703-dev-ed--c.visualforce.com/apex/iframe';
origin = 'http://velocity-energy-3703-dev-ed--c.visualforce.com';

constructor() {
    super();

    this.template.addEventListener('message', function(event) {
        console.log(event);
        if (event.origin !== origin) {
            // Not the expected origin: Reject the message!
            return;
        }
        // Handle the message
        console.log(event.data);
    }, false);
}

// adding a callback to see if this works
connectedCallback(){

    this.template.addEventListener('message', function(event) {
        console.log(event);
        if (event.origin !== origin) {
            // Not the expected origin: Reject the message!
            return;
        }
        // Handle the message
        console.log(event.data);
    }, false);
}

sendData(){

    var message = 'testing';
    this.template.querySelector('iframe').contentWindow.postMessage(message, origin);

}

VF

  <apex:page showHeader="false" standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0" >

    <script>

        var lexOrigin = "https://velocity-energy-3703-dev-ed.lightning.force.com";
        window.addEventListener("message", function(event) {
            console.log('Origin '+ event.origin);
            console.log('data '+ event.data);
            if (event.origin !== lexOrigin) {
                // Not the expected origin: reject message!
             return;
            }

        });

    </script>

</apex:page>
4

On the "sendData" method the origin variable needed to be preceded with "this" as it wasn't being recognised otherwise

    sendData(){
        let message = 'testing';
        this.template.querySelector('iframe').contentWindow.postMessage(message, this.origin);


    }
| improve this answer | |
2
+25

Make sure the target window you're/FB is posting messages to is loaded. Most of the time I usually get this error when a hidden iframe I was sending messages to, failed to load.

If this doesn't work change the: origin = 'https://******.visualforce.com'; to 'http://******.visualforce.com';

| improve this answer | |
  • I added an onload and still getting same issue. tried your url suggestion but not difference. see the updated code above thanks! – JPG Mar 26 '19 at 18:16
  • Remove anything referring to an HTTPS website and rename it to an HTTP. – Harry Smith Mar 27 '19 at 9:33
2

Possible issue could be your VF page might not have loaded by the time you are posting from lightning component.

Add an event listener to your lightning component, which listens for message . In your VF, you do window.onload() function, where you postmessage to your lightning component with body 'loaded'. When your VF is loaded, it sends out a message, lightning component will receive the message. After you receive the message, it is sure that VF has loaded completely so that you can send message from lightning component

| improve this answer | |
  • still getting the same message. I updated my code snippet so you can see what I'm trying to do better – JPG Mar 26 '19 at 18:15
1

From what I have read above; I believe you need to use the renderedCallback() method, which is a part of the rendering lifecycle of an LWC and runs once the rendering phase has completed.

You can see the Component Lifecycle info here.

So you would need the following instead:

renderedCallback(){
    window.addEventListener('message', function(event) {
        console.log(event);
        if (event.origin !== origin) {
            // Not the expected origin: Reject the message!
            return;
        }
        // Handle the message
        console.log(event.data);
    }, false);
}

From a logic standpoint it makes a lot of sense, you need to wait until the rendering lifecycle has completed in order for you to access the iFrame, if you execute your code on Constructor or Connection, then the iFrame has not yet been able to load.

I have also not yet tested this properly... so don't hate me if it doesn't work 100%!

| improve this answer | |

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.