[SalesForce] Lightning container with external source

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"    
                  type="String" 
                  default="https://www.google.com" 
  />

  <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:

<iframe
  id="iframe"
  aura:id="iframe"
  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');
    console.log(iframe);

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

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

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

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

Best Answer

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' }, '*');