Embedding Retool - Message to Parent

Hi all,
I am going spare trying to get parent.postMessage functionality to work, I wondered if someone could help me. I am following the docs and trying to have my embedded retool app send data to the parent via parent.postMessage. I have tried this in multiple browsers to the same outcome. I also have turned on the Enable parent window communication functionality in beta settings.

I am using the below code (throwing the kitchen sink at the problem as you can see), which is triggered on a button press).

Do we need to supply a domain? If we do how would that work on a local build (eg 127.0.0.1). I am supplying all the options, the retool public shared link, the domain the app is embedded in and localhost.

parent.postMessage("HI BABYGIRL", "https://mysubdomain.mydomain.net")
parent.postMessage("HI BABYGIRL")
parent.postMessage("HI BABYGIRL", "https://xxx.retool.com/embedded/public/757848484848474-474974")
parent.postMessage("HI BABYGIRL", "127.0.0.1")
parent.postMessage("HI BABYGIRL", "http://127.0.0.1")

I am using the below methods to receive data:

const onRetoolDataReceived = (event: AnyIsOk) => {
    console.log(event);
  };

  useEffect(() => {
    onRetoolDataReceived(event);
  }, [onRetoolDataReceived]);

  window.addEventListener(
    'message',
    function (e) {
      console.log('Parent window received: ', e.data, e);
    },
    false,
  );

  window.addEventListener('message', event => {
    if (event.origin !== 'https://myretoolname.retool.com') {
      // Check the origin of the message to ensure it's from your Retool instance
      return;
    }

    if (event.data.eventType === 'retoolData') {
      console.log('Data received from Retool:', event.data.payload);
      // Process the received data as needed
    }
  });

And this is the embed:

   <Retool
              height="100%"
              width="100%"
              allow={'true'}
              sandBox={'true'}
              onData={(event: AnyIsOk) => {
                console.log( event, event.data);

                onRetoolDataReceived(event);
              }}
              url={
                'https://mylink.retool.com/embedded/public/6484636393783-484864
              }
        
            />

And I am receiving the below on render:

[Log] Parent window received:  – "hello there" – MessageEvent {isTrusted: true, origin: "https://myretoolname.retool.com", lastEventId: ""} (routes.providers.c63350f8.js, line 1)
MessageEvent {isTrusted: true, origin: "https://myretoolname.retool.com", lastEventId: ""}MessageEventbubbles: falsecancelBubble: falsecancelable: falsecomposed: falsecurrentTarget: nulldata: "hello there"defaultPrevented: falseeventPhase: 0isTrusted: truelastEventId: ""origin: "https://myretoolname.retool.com"ports: []Array (0)returnValue: truesource: Window {listeners: Object}WindowsrcElement: Window {listeners: Object}Windowtarget: Window {listeners: Object}WindowtimeStamp: 383926type: "message"MessageEvent Prototype

So it looks like it has the capability to work?

But when I trigger the javascript event, nothing happens when embedded (I get a trigger message when testing within retool however).

Can anyone help? It would be very much appreciated - I am just trying to get some text from a retool form.

Many thanks.
Chris

Hey @Chris_Phillips!

Both window.addEventListener declarations should work :thinking: ran a quick test based on your example and the following seems to work for me:

React Code
    import React, { useEffect } from "react";
    import Retool from "react-retool";

    const PUBLIC_APP_LINK = /*your public app link*/;
    const APP_ORIGIN = /*https://yourdomain.retool.com*/;

    function App() {
      useEffect(() => {
        const logMessage = (event) => {
          console.log("Log triggered");

          if (event.origin !== APP_ORIGIN) {
            // Check the origin of the message to ensure it's from your Retool instance
            console.log('Wrong origin!')
            return;
          }

          if (event.data.eventType === 'retoolData') {
            console.log('Data received from Retool:', event.data.payload);
            // Process the received data as needed
          }
        }

        window.addEventListener("message", logMessage);

        return () => window.removeEventListener("message", logMessage);
      }, [])

      return (
        <div className="App">
          <div className="parent-react-app-container">
            <div className="retool-box">
              <Retool url={PUBLIC_APP_LINK} />
            </div>
          </div>
        </div>
      );
    }

    export default App;

The app itself is just a button that triggers the following JS query (embedded_app.json):

JS Query Code
    parent.postMessage({eventType: "retoolData", payload: "This is a test message :)"}, urlparams.href);
    utils.showNotification({title: "Message posted!"})

Using urlparams.href is particularly handy so that you don't have to manually copy the URL over. Curious to know if you see any differences in the code or otherwise if you notice any other errors in your browser's dev tools :thinking:

1 Like

Thanks Kabirdas,

I tried using your suggestions but getting the same result (on a local build).
I am getting this error in the console, could this be related?

DevTools failed to load source map: Could not load content for https://retoolsentrysourcemaps-secondary.z5.web.core.windows.net/DesignSystemIcons.c4801d9138bf4db3c298.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

:thinking: do you know where the -- "hello there" -- message is coming from in your app? Do you happen to be using release versions?

1 Like

You cracked it - it was releases, I wasn't aware they existed, none of my changes were made live.

Thanks for the help.

Awesome! Glad that works :grin:

1 Like