5

Problem statement:

When we try to access the 'window.opener.$A' property of lightning component present in the parent from a javascript snippet present in a child window (Visual force page) we get the error 'Permission denied to access property "$A"'

Task:

We intend to open a child window on click of a button present in a lightning component. The child window would present the user with certain selectable data. Once the user selects certain row, and clicks submit, the row data(obtained by the child window using callouts) has to be returned to the parent lightning component/App which opened the child window(containing VF page).

Activities completed:

  • We created a 'Application' level global access event named as 'ICDCodeSelected' (Syntax for which is as follows), which we want to utilize to pass data from child window to parent window's lightning component.

    <aura:event type="APPLICATION" description="Event template" access="global">
        <aura:attribute name='CODE' type='String'/>
        <aura:attribute name='DESCRIPTION' type='String'/>
    </aura:event>
    
  • As per mentioned in SF documentation : Firing Lightning Events from Non-Lightning Code, we have added following code snippet to our Visualforce Page javascript which is as follows:

    var myExternalEvent;
    if(window.opener.$A && (myExternalEvent = window.opener.$A.get("e.c:ICDCodeSelected"))) {
        myExternalEvent.setParams({CODE:'M84.3',DESCRIPTION:'Home visit for the evaluation and management of a new pat..'});
        myExternalEvent.fire();
    }
    

Note:

Please note that the error appears for 'window.opener.$A' only, when we include the lightning dependency application/component inside the VF page (child window) using lightning out, we can access the $A component ad hence can get the Event to fire it, but it fires only in the context of the child window, and their is not update on the parent lightning page.

Your inputs/comments/suggestions on the above issue resolutions would be pretty helpful for us.

Thanks, Abhijeet Bhandari

  • can you trying using window.$A instead of window.opener.$A? – Praveen May 13 '17 at 13:07
  • @Praveen They already tried that. – sfdcfox May 13 '17 at 13:28
  • @sfdcfox I'm not sure whether they have tried it or not. Which part in the question, has OP has mentioned they have tried window.$A?. I couldn't find it. – Praveen May 13 '17 at 13:40
  • @Praveen ...when we include the lightning dependency application/component inside the VF page (child window) using lightning out, we can access the $A component ad hence can get the Event to fire it, but it fires only in the context of the child window... – sfdcfox May 13 '17 at 15:00
  • @Praveen the syntax 'window.$A' would be able to access the '$A' property for current window/child window only (lightning dependency app in child window), but it won't be able to access the '$A' property of the parent window which opened it until I use the syntax 'window.opener.$A' – Abhijeet Bhandari May 14 '17 at 14:15
2

A solution for similar problem has been provided here https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html

Some relevant section from the above blog:

Visualforce Page to Lightning Component

In this second scenario, we still have the same arrangement: a Visualforce page wrapped in a Lightning component. This time we need communication to happen in the opposite direction: The Visualforce page sends messages to the Lightning component.

Sending the Message in a Visualforce Page

This time, we invoke postMessage() on parent. This is a reference to the parent window, in other words the main window in Lightning Experience that hosts Lightning components.

<apex:page>
  <input id="message" type="text"/>
  <button onclick="sendToLC()">Send to LC</button>

  <script>
    var lexOrigin = "https://yourdomain-dev-ed.lightning.force.com";

    function sendToLC() {
       var message = document.getElementById("message").value;
       parent.postMessage(message, lexOrigin);
    }

  </script>
</apex:page>

Code highlights: lexOrigin is the origin (protocol + port + host) Lightning Components are loaded from The message field is used to capture the simple string message we will send to the Lightning Component

The second argument of postMessage() is the origin of the parent window. Again, the event will not be sent if the content of the parent window at the time postMessage() is called wasn’t loaded from lexOrigin.

Receiving the Message in a Lightning Component

To receive the messages in your Lightning Component, you set up a listener for message events:

Component:

<aura:component implements="flexipage:availableForAllPageTypes" 
            access="global">

<aura:attribute name="vfHost" type="String" 
    default="yourdomain-dev-ed--c.na35.visual.force.com"/>

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<iframe aura:id="vfFrame" src="{!'https://' + v.vfHost + '/apex/myvfpage'}"  
/>     
  </aura:component>

Controller:

({
    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);
  }
 })

Code Highlights: vfOrigin is the origin (protocol + port + host) Visualforce pages are loaded from. This is where we expect the messages to come from.

event.origin is the actual origin of the window that sent the message at the time postMessage() was called. You should always verify that the actual origin and the expected origin match and reject the message if they don’t.

event.data is the message sent from the other window With this infrastructure in place, the Lightning component can now listen for events sent by the Visualforce page and forward any relevant events to other Lightning components on the page using standard Lightning application events.

  • Thanks a lot @slQh for your inputs. For anyone facing the same issue I would like to point out, that the root cause for the error was the cross domain reference of the $A property. Since VF pages do load with URL 'instance.visual.force.com', and lightning with 'instance.lightning.force.com' hence the permission issue. The blog mentioned in the answers gets you around that exact problem. – Abhijeet Bhandari May 20 '17 at 15:53

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.