Embed VF page in LWC & two-way Communication

by Rijwan Mohmmed
embed-vf-page-in-lwc-two-way-communication-Salesforce-techdicer

Hello folks, today we are going to discuss Embed VF page in LWC & two-way Communication. Here we will Embed the Visualforce page in the LWC component and call their method with parameters.

embed-vf-page-in-lwc-two-way-communication

Also, check this: Call Visualforce Method From LWC

Key Highlights :

  1. As the VF 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 from the VF page.
  2. Visualforce pages and Lightning Components are served from different domains.
  3. We will be using window.postMessage() for pass data.
  4. Use iframe to embed the VF page.

Process & Code :

Step 1: First of all We create a Visualforce Page so we can embed this in LWC.

LWCWithVfPage.vfp:

<apex:page sidebar="true" showHeader="true">
    <apex:slds />
    <apex:form id="form1">
        <apex:pageBlock title="Showing data from LWC component">
            <apex:pageBlockSection >
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Name" />
                    <apex:outputText styleClass="name" />
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="City" />
                    <apex:outputText styleClass="city" />
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="Send Data to LWC component">
            
            <div class="slds-p-around_medium">
                <div class="slds-form-element">
                    <label class="slds-form-element__label" for="form-element-01">Message</label>
                    <div class="slds-form-element__control">
                        <textarea id="messageId" placeholder="type message" class="slds-textarea"></textarea>
                    </div>
                </div>
                <!--Button to call Javascript method-->
                <div class="slds-m-top_small slds-text-align_center">
                    <button class="slds-button slds-button_brand" onclick="sendDataToLWC();return false;">Send Message To LWC</button>
                </div>
            </div>
        </apex:pageBlock>
    </apex:form>
    
    <script>
    	var lexOrigin="https://rijudelta-dev-ed.lightning.force.com";
    
        function sendDataToLWC() {
            let msg = document.getElementById('messageId').value;
            var message = {
                name:"EmbedVflwc",
                payload:msg
            };
            console.log(message);
            parent.postMessage(message, lexOrigin);
        }
    
        window.addEventListener("message", function(event){
            if(event.origin !== lexOrigin || event.data == undefined){
                //Not the expected origin
                return;
            }
            
            if(event.data.Name || event.data.City){
                let name = event.data.Name;
                let city = event.data.City;
                document.getElementsByClassName("name")[0].innerHTML = name;
                document.getElementsByClassName("city")[0].innerHTML = city;
            }
        },false);
	</script>
</apex:page>

Step 2: Here we create the LWC component and Embed the above VF page in this component.

embedvflwc.html:

<template>
	<lightning-card variant="Narrow" title="Send Data to VF Page" icon-name="standard:account">
		<div class="slds-p-horizontal_small">
			<div class="slds-p-around_medium lgc-bg">
				<lightning-input type="text" label="Name" onchange={handleName} value={Name}></lightning-input>
			</div>
			<div class="slds-p-around_medium lgc-bg">
				<lightning-input type="text" label="City" onchange={handleCity} value={City}></lightning-input>
			</div>
			<!-- call child method -->
			<div class="slds-p-around_medium lgc-bg" style="text-align: end;">
				<lightning-button variant="brand" label="Call VF Page Method" title="Call Child"
					onclick={callVFPageMethod} class="slds-m-left_x-small"></lightning-button>
			</div>
		</div>
	</lightning-card><br/>
    <lightning-card variant="Narrow" title="Show Data From VF Page" icon-name="standard:account">
        <div class="slds-p-horizontal_small">
			<div class="slds-p-around_medium lgc-bg">
                Message : {messageFromVF}
			</div>
        </div>
    </lightning-card><br/>
    <iframe id="LWCWithVFPage" src="/apex/LWCWithVFPage" width="100%" height="350px"> </iframe>
</template>

embedvflwc.JS:

import { LightningElement } from 'lwc';
export default class EmbedVflwc extends LightningElement {
    vfRoot = "https://rijudelta-dev-ed--c.vf.force.com";
    Name = '';
    City = '';
    messageFromVF;

    connectedCallback() {
        window.addEventListener("message", (message) => {
            console.log(message.origin);
            if (message.origin !== this.vfRoot) {
                //Not the expected origin
                return;
            }

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

    handleName(event) {
        this.Name = event.detail.value;
    }

    handleCity(event) {
        this.City = event.detail.value;
    }

    callVFPageMethod() {
        var vfWindow = this.template.querySelector("iframe").contentWindow;
        let paramData = { Name: this.Name, City: this.City };
        vfWindow.postMessage(paramData, this.vfRoot);
    }
}

embedvflwc.JS-xml :

<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>57.0</apiVersion>
	<isExposed>true</isExposed>
	<targets>
		<target>lightning__HomePage</target>
	</targets>
</LightningComponentBundle>

Output :

Reference :

  1. LWC
  2. iframe
What’s your Reaction?
+1
1
+1
0
+1
0
+1
0
+1
0
+1
0

You may also like

Leave a Comment