krakenjs / post-robot

Cross domain post-messaging on the client side using a simple listener/client pattern.
Apache License 2.0
746 stars 91 forks source link

Question about mulitple iframes support #56

Closed nosus closed 6 years ago

nosus commented 6 years ago

I am working on a web application that it needs to support multiple 3rd party iframe to be embedded in the same page, and need communication between the parent page and those iframes. they should all have the same set of API calls from the parent to child iframe and vice versa.

for example, parent page will send some data to each child iframe and each child iframe may send certain data back.

From what I have read about post-robot so far, do I have to make all the event name unique? if so, that brings another problem that how does the child iframe (3rd part code) know what's the unique event identifier is? Do I have to put it in the iframe URL or set up another postMessage event to pass it?

Does post-robot have some feature which can make the event listen iframe scoped?

Thank you very much for you help.

bluepnume commented 6 years ago

The event name only needs to be unique for a single frame. If you're listening from multiple frames, you can listen for the same event name from each frame without any problems.

nosus commented 6 years ago

Thanks @bluepnume

What about sending data from parent to child iframe? I think parent need to call send with a unique event name and code inside the iframe need to have on with the same unique event name as well?

bluepnume commented 6 years ago

That should work fine. The child can specify { window: window.parent } to make sure it's only listening to messages from the parent.

nosus commented 6 years ago

sorry, I am not sure I get your point. maybe I didn't express my problem clearly enough, sorry for that.

The use case is I want to be able to send different data to different child iframes and also allow them to send data back, so if the parent page call send with same event name but different data multiple times, will all the iframe get those data? how can the child iframe tell which data it should use?

it would be great if we have another parameter which can bind the send/on with the iframe id, or something like that? then in the iframe developer can just write code to listen to /response to the same event, but at the parent level, it can send different data to the different iframes with the same code but just different iframe id?

I ran into a very old library, https://github.com/ternarylabs/porthole, which allow you to create multiple proxy objects for multiple iframe instances, and with each proxy object, communication is only between parent and that particular iframe, I wonder how to get the same thing with post-robot?

bluepnume commented 6 years ago

Hi,

if the parent page call send with same event name but different data multiple times, will all the iframe get those data

You choose exactly which iframes you're going to send messages to.

postRobot.send(window.frame1, 'getUser').then(event => {
    console.log('Got user from frame1:', event.data.user);
});

postRobot.send(window.frame2, 'getUser').then(event => {
    console.log('Got user from frame2:', event.data.user);
});

So with post-robot you're always explicit about which windows you're sending to. The message will only go to the frame you pass to send().

Then in the iframe, you can choose to listen for messages from any window:

postRobot.on('getUser', function(event) {
    return {
        name: 'Guybrush Threepwood'
    };
});

Or you can choose to listen for messages from only the parent window:

postRobot.on('getUser', { window: window.parent }, function(event) {
    return {
        name: 'Guybrush Threepwood'
    };
});

Does that make sense for your question?

nosus commented 6 years ago

cool, thanks for the code above, so it solves the first part, that each iframe will get its own data with the same code (listen to the same event).

What's about the other way around? if the child iframe what to send some data to parent, not inside an on method, but using send with the same event name, like when user input something and click the submit button, guess it needs to pass a unique identifier with the data sent?

bluepnume commented 6 years ago

In that case the parent can specify the iframe as the window to receive messages from:

postRobot.on('getUser', { window: window.frame1 }, function(event) {
    return {
        name: 'Guybrush Threepwood'
    };
});
nosus commented 6 years ago

oh, right, that's it! Guess I totally missed the window configuration part. Thanks a lot @bluepnume

btw, I probably should ask this in the xcomponent repository but seems like you are the master of that as well. I am with Angular and seems it's easier if I use xcomponent and just create call MyLoginXComponent.render({... multiple time for each iframe id, is that correct?

nosus commented 6 years ago

if I want to give the 3rd party develop (who is developing the page inside the iframe) a SDK for communicate with the parent but hide all the technical details, like they don't even need to know post-robot or xcomponent, the initialization code of my sdk will handle create the component and set up listeners, for the xcomponent, the 'tag' attribute, do I need to make sure that's unique?

nosus commented 6 years ago

one more question, promise this is the last one :)

when I use post-robot or xcomponent, do I need to make sure the child iframe is loaded (something like listening to domContentloaded event) before I send any data or it's already been taken care of? I don't see any code related to that in the Angular demo of xcomponent, in the iframe it just creates a component and fetches the data prefillMailaddress directly.

bluepnume commented 6 years ago

seems it's easier if I use xcomponent and just create call MyLoginXComponent.render({... multiple time for each iframe id, is that correct?

Yeah, this means you don't need to worry about setting up so many listeners. You just pass functions/callbacks down into the iframe.

the 'tag' attribute, do I need to make sure that's unique?

A single xcomponent needs a unique tag, but you can render a component multiple times.

when I use post-robot or xcomponent, do I need to make sure the child iframe is loaded (something like listening to domContentloaded event) before I send any data or it's already been taken care of?

If you're using xcomponent you should pass down data using props, rather than calling send(). Then that data, or any callbacks you pass, will be available in window.xprops inside the iframe.

nosus commented 6 years ago

sorry for the late, but Thank YOU very much @bluepnume I am using the post-robot in my project now and it works perfectly.