7

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>
1
  • Why have you added constructor and connectedcallback in this?
    – Sarang
    Commented Jun 1, 2021 at 7:55

4 Answers 4

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);


    }
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';

2
  • I added an onload and still getting same issue. tried your url suggestion but not difference. see the updated code above thanks!
    – JPG
    Commented Mar 26, 2019 at 18:16
  • Remove anything referring to an HTTPS website and rename it to an HTTP. Commented Mar 27, 2019 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

1
  • still getting the same message. I updated my code snippet so you can see what I'm trying to do better
    – JPG
    Commented Mar 26, 2019 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%!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .