97

I've been following this tutorial - http://www.youtube.com/watch?v=R2hOvZ7bwXU, which explains how to use postMessage to securely pass a message between iframe and parent - you basically end up with something like this - http://html5demos.com/postmessage2

My problem is that I need it to work the opposite way round (child to parent) and don't know how to target the parent window.

this is my receiver code (in the parent):

function handleMsg(e) {
    if(e.origin == "http://uc.dialogue.net") {
        let blah = e.data;
        alert(blah);    
    } else {
        alert("error");
    }
}
addEventListener("message", handleMsg, true);

and this is the sender function that is triggered by a simple form (in child):

   let text = document.querySelector('.srchInput').value;
   window.parent.postMessage(text, "http://uc.dialogue.net");   

Should I be targeting the parent in a different way?

Cheers Paul

Avindra Goolcharan
  • 4,032
  • 3
  • 41
  • 39
Dancer
  • 17,035
  • 38
  • 129
  • 206

3 Answers3

144
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

// Listen to message from child window
eventer(messageEvent,function(e) {
    var key = e.message ? "message" : "data";
    var data = e[key];
    //run function//
},false);

Got it to work with the above in the parent page and the following in the child page -    

parent.postMessage("loadMyOrders","*");  //  `*` on any domain         

Code copied from here.

Olli
  • 1,231
  • 15
  • 31
Dancer
  • 17,035
  • 38
  • 129
  • 206
  • 3
    Awesome! Note that in the eventer listener, `e.message == "loadMyOrders"` – bergie3000 Dec 05 '12 at 21:12
  • 3
    Thanks for that. Though in Chrome I have `e.data == "loadMyOrders"`. – Daniel Buckmaster Jan 09 '13 at 10:49
  • 8
    Sometimes you need to use window.opener.postMessage(); For example if child window had some redirects. – Aldekein Feb 15 '14 at 12:18
  • @iautomation how did you do it in Android WebView this is my problem as well... Your response would be appreciated. – Ariel Magbanua Jan 28 '15 at 05:33
  • 33
    Downvoted only because the code was taken verbaitum from [David Walsh's blog](http://davidwalsh.name/window-iframe) without at least citing it as the source. – Scotty C. Mar 06 '15 at 01:10
  • how to send message to child iframe? I want to get cookie form third party website to my iframe. – Yatin Mistry Mar 11 '15 at 06:25
  • 1
    This works for sending messages from an iFrame to its parent—but on the parent page, I had to put the listener before the ` – Joe Mornin Aug 09 '15 at 15:58
  • 16
    For anyone reading this answer in the future, please do not include all the boilerplate junk, which is only needed for ie <= 8 . Just use `addEventListener` directly. http://caniuse.com/#feat=addeventlistener Thank you :) – Avindra Goolcharan May 05 '16 at 17:29
  • Agreeing with @AvindraGoolcharan's edit (and alternate answer below), the first three lines should be omitted in any website today. – Don McCurdy Mar 08 '18 at 16:48
36

Unpacked the accepted answer using newer ecma262 spec, and dropping ie8 support:

window.addEventListener('message', e => {
    const key = e.message ? 'message' : 'data';
    const data = e[key];

    // ...
},false);

Relevant documentation:

Avindra Goolcharan
  • 4,032
  • 3
  • 41
  • 39
4

This is a React version based on Avindra Goolcharan's answer:

const MessageHandler = ({ allowedUrl, handleMessage }) => {
  useEffect(() => {
    const handleEvent = event => {
      const { message, data, origin } = event;
      if (origin === allowedUrl) {
        handleMessage(message || data);
      }
    };

    window.addEventListener('message', handleEvent, false);
    return function cleanup() {
      window.removeEventListener('message', handleEvent);
    };
  });

  return <React.Fragment />;
};

Where allowedUrl is the URL loaded within the iframe and handleMessage is a redux-connected function (or other form of state management) letting the rest of the app know about the received message.

sheba
  • 800
  • 6
  • 14