Communication Between Lightning Web Component and Visualforce Pages in Salesforce | LWC Stack ☁️⚡️

 In this blog I will show you how you may communicate between LWC to VF page and vice versa.

Visualforce page and Lightning Components can coexists, while communicating between them you need to take care of few things.

Different DOM Elements : As the visualforce page will be in an iframe so the DOM elements of the Lightning Component and VF page will be different. And also the window object will be separate for VF page.

Different Origin : Visualforce page and Lightning Components are having their different origins. For lightning component it will be ending with lightning.force.com and for visualforce pages it will be ending with visualforce.com

Now the question is why it's difficult to communicate with different origin pages?

Answer : It is due to browsers Same Origin Policy, this prevents page to pass or receive code/data from a different origin page.

This is due to security reasons. But fortunately we are having an API to do this securely. 

To do this we will be using window.postMessage()

Please checkout below examples - 

Example 1 - Pass data from LWC to Visualforce Page

SendToVF.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
  <lightning-card title="LWC to Visualforce">
    <div class="slds-p-around_small">
      <lightning-input
        type="text"
        label="Enter some text"
        value={message}
        onchange={handleOnChange}
      ></lightning-input>
      <br />
      <lightning-button
        variant="brand"
        label="Send to VF"
        title="Primary action"
        onclick={handleClick}
        class="slds-m-left_x-small"
      ></lightning-button>
      <br />
      <br />
      <iframe id="vfIframe" src="/apex/SampleVF"> </iframe>
    </div>
  </lightning-card>
</template>


SendToVF.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { LightningElement } from "lwc";

export default class SendToVF extends LightningElement {
  vfRoot = "https://enterprise-nosoftware-7728-dev-ed--c.visualforce.com/";
  message = "";
  handleOnChange(event) {
    this.message = event.target.value;
  }
  handleClick() {
    var vfWindow = this.template.querySelector("iframe").contentWindow;
    vfWindow.postMessage(this.message, this.vfRoot);
  }
}


SampleVF.page

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<apex:page>
<!-- Begin Default Content REMOVE THIS -->
<h1>Congratulations</h1>
This is your new Page
<!-- End Default Content REMOVE THIS -->
<p id="messageFromLWC" style="font-weight:bold; font-size:x-large"> </p>
<script>
    var lexOrigin ="https://enterprise-nosoftware-7728-dev-ed.lightning.force.com";
    window.addEventListener("message",function(event){
        if(event.origin !== lexOrigin){
            //Not the expected origin
            return;
        }
        document.getElementById("messageFromLWC").innerHTML = 'Text from LWC : '+event.data;
    },false);
</script>
</apex:page>


Example 2 - Pass data to LWC from VF page

SampleVFToLWC.page

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<apex:page>
    <br/>
<input id="message" type="text"/>
<button onclick="sendToLWC()">Send to LWC</button>

<script>
    var lexOrigin="https://enterprise-nosoftware-7728-dev-ed.lightning.force.com"
    function sendToLWC() {
        var payload = document.getElementById("message").value;
        var message = {
            name:"SampleVFToLWCMessage",
            payload:payload
        };
        parent.postMessage(message,lexOrigin);
    }
    
</script>
</apex:page>


SendToLWC.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<template>
  <lightning-card title="Visualforce to LWC">
    <div class="slds-p-around_small">
      Hello I am a Lightning Web Component
      <br />
      <p style="font-weight: bold; font-size: x-large">{messageFromVF}</p>
      <br />
      <iframe id="vfIframe" src="/apex/SampleVFToLWC"> </iframe>
    </div>
  </lightning-card>
</template>


SendToLWC.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import { LightningElement } from "lwc";

export default class SendToLWC extends LightningElement {
  messageFromVF;
  connectedCallback() {
    var VfOrigin =
      "https://enterprise-nosoftware-7728-dev-ed--c.visualforce.com";
    window.addEventListener("message", (message) => {
      if (message.origin !== VfOrigin) {
        //Not the expected origin
        return;
      }

      //handle the message
      if (message.data.name === "SampleVFToLWCMessage") {
        this.messageFromVF = message.data.payload;
      }
    });
  }
}


NoteWhen you pass the data from LWC to Visualforce, in that case we wrapped the iframe and did iframe.postMessage(), there can be only one visualforce page url in that iframe so that is always going to be one to one. 

But when you send a message from visualforce to lwc so for that we have to do parent.postMessage, here parent is a reference to our main window in lightning experience where other LWC may also exists and if they are also having an event listner then they will also receive the visualforce message. This is one to many messaging. To avoid this we should name our message and then check for the same while listning to it in the LWC.


Output


Checkout complete video tutorial below

 If you have any question please leave a comment below.

If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !

Thanks
Happy Coding :)

Post a Comment

0 Comments