We will use the following code snippets to demonstrate this use case.
The Visualforce code is as follows. Observe the highlighted code where we post the message to the parent domain (in this case, the Lightning domain). We have obtained the domain dynamically using the Apex controller code that is linked to the Visualforce page. Let's name the Visualforce page testVF:
<apex:page controller="vfController">
<apex:slds/>
<input id="message" type="text"/>
<button onclick="sendToLC()">Send to LC</button>
<script>
var lexOrigin = "https://{!JSENCODE(SalesforceDomain)}. Lightning.force.com";
console.log(lexOrigin);
function sendToLC() {
var message = document.getElementById("message").value;
console.log('Message To Send..'+message);
parent.postMessage(message, lexOrigin);
}
</script>
</apex:page>
The following code is for an Apex controller that gets the domain to the Visualforce code:
public with sharing class vfController {
public String getSalesforceDomain(){
return System.Url.getSalesforceBaseURL().getHost().substringBefore('--');
}
}
The Lightning Component uses a listener on the window object to listen for messages:
<aura:component implements="flexipage:availableForAllPageTypes"
access="global">
<aura:attribute name="message" type="String"/>
<aura:attribute name="vfHost" type="String"
default="computing-inspiration-8620-dev-ed--c.cs62.visual.force.com"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div>
<!-- The Visualforce page to send data to -->
<iframe aura:id="vfFrame" src="{!'https://' + v.vfHost + '/apex/testVF'}" />
</div>
</aura:component>
The controller function is as follows. In the following code, the snippet that provides the ability to listen for messages is highlighted:
({
doInit : function(component) {
var vfOrigin = "https://" + component.get("v.vfHost");
window.addEventListener("message", function(event) {
if (event.origin !== vfOrigin) {
// Not the expected origin: Reject the message!
return;
}
// Handle the message
console.log(event.data);
}, false);
}
})