I would like to have an iframe in a Lightning component.

I, first, tried to create a lightning:container as this:

  <aura:attribute name="url"    

  <lightning:container src="{! v.url}" 
                       onerror="{! c.onError }" 
                       onmessage="{! c.onMessage }" />

but according to documentation:

lightning:container allows you to use an app developed with a third-party framework, such as AngularJS or React, in a Lightning component. Upload the app as a static resource.

So I decided to use an iframe as this:

  style="{! v.style }"
  src="{! v.url}"
  width="{! v.width }"
  height="{! v.height }"
  scrolling="{! v.scrolling }"
  onerror="{! c.onError }"
  frameborder="{! v.frameBorder }"
  sandbox="{! v.sandbox }"

And setting up the eventListener on message during Lightning Component initialisation :

  function(component, event, helper) {
    const iframe = component.find('iframe');

    iframe.addEventHandler('message', (event) => {
      console.log('received message');
    }, false); // It works

    const frame = document.getElementById('iframe');
    console.log(frame); // null
    frame.addEventListener('message', (event) => {
      console.log('received message');
    }, false)

    frame.postMessage({ test: 'test' }, '*');

This works (receiving message) but I can not do component.find('iframe').postMessage(). Instead I tried to perform a querySelector on id but I am not able to get the HTML Element to perform a post message.

Do you have any workaround to do so ? (Version 41.0).

Lightning Container Documentation


HTML elements are rendered as aura:html components, so you need to get elelment first:

var iframe = component.find('iframe').getElement();

should return the html element, but be aware, that it will only be available after the component is rendered, as described here.

In case you are using a init handler I would suggest using render instead (docu):

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

So your action could call it like this:

iframe.getElement().postMessage({ test: 'test' }, '*');
  • getElement does not return anything I will then try in after rendering function.
    – Simonp
    Dec 7 '17 at 11:12
  • @SimonPlacentino updated my answer with a render handler.
    – Basti
    Dec 7 '17 at 11:24
  • iframe.getElement().postMessage({ test: 'test' }, '*'); in the render handler leads to an infinite loop. Someone could confirm me that doing component.find('iframe').addEventHandler('message') and component.find('iframe').getElement().addEventListener('message') is equivalent because handled by Lightning ?
    – Simonp
    Dec 7 '17 at 12:31
  • @SimonPlacentino Where does the loop come from? were you able to debug anything? The Handler/Listener thing seems to be another question.
    – Basti
    Dec 7 '17 at 16:35
  • 1
    forget about this. What I did: onInit of component, dynamically create the iFrame with $A.createComponent and addEventListener('message') on my current window object (the only way for me to receive a message): and it works. Thank you anw
    – Simonp
    Dec 8 '17 at 7:28

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.