Embedding public apps and issue passing data from the parent window

Goal:

Embed a public Retool app into the content editor for a web page, and then pass data from the parent window into the Retool app.

Details:

I read this how-to doc: Embed web apps | Retool Docs (do we need to use Retool's React or JavaScript SDKs in order to do this?) and this community post on passing data to embedded apps. I'm having trouble with the ParentWindow query and can't get it to return anything. Is embedding apps using Retool's React or JavaScript SDKs required in order to pass data from the parent window into an embedded Retool app? What am I missing here? :thinking:

Steps:

To test it out, I did the following:

  1. Add a ParentWindow query with Selector #myCustomData to the Retool app I'm going to embed. Include a console log of the data in the transformer for this query to see what it's returning.
  2. Create a simple HTML doc containing my <iframe> Retool app embed code and a <div id="myCustomData"> with JSON formatted content to pass into my Retool app.
<!DOCTYPE html>
<html>
    <body>

        <p>div id="myCustomData" is below</p>
        <div id="myCustomData">{"myData":"myStringValue"}</div>

        <iframe src="https://essex.retool.com/embedded/public/..." width="100%" height="800px"></iframe>

    </body>
</html>
  1. Open the HTML file in Chrome and open the Chrome Devtools console.
  2. Observe that the parent window query data is undefined
  3. From the console, run document.querySelector('#myCustomData').textContent
  4. Observe that there is content returned

After this, I also tried a couple more things that didn't work:

  • hooking up the button in my Retool app to trigger the ParentWindow query (to see if there was any different in triggering it on-click from my HTML page)
  • removing the transformer from the ParentWindow query (in case transformers are not supported on ParentWindow queries)

Screenshots:

Retool app ParentWindow query

View of the ParentWindow query not returning data, though there is content in the Selector it's configured with

1 Like

I was able to get data from ParentWindow query by using the Retool Embed SDK (tested out via CodePen, this is so cool!!) :tada:

@Darren you mentioned in office hours today that the Retool Embed SDK and React Retool packages use the built-in window.postMessage() API to do the communication between parent window and retool. In the CodePen console I see Received message from parent logs, which I never saw from my HTML page. It seems like that's the missing link and why my simple HTML doc solution won't work. Did you get a chance to check out your old apps to see whether you were/still are able to use ParentWindow queries on a plain HTML page? Thank you!

1 Like

Nice! Glad to hear it, @sgodoshian. :slightly_smiling_face:

I looked back at some previous projects and it is necessary to define event handlers on the parent page, whether via custom JS or one of the packages we provide. Hopefully that isn't too large a lift for your particular use case, as the functionality is pretty slick!

I'm happy to help with any additional configuration, so don't hesitate to follow up here.

1 Like

Thank you, @Darren! Could you please share your custom JS for the event handlers you defined on the parent page? Seeing an example would be really helpful. Thank you!

Of course! This is basically just a stripped down version of what our packages do, but with the ability to customize its behavior a bit.

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script defer>
    window.addEventListener('message', e => {
      if (e.origin === 'https://toula.retool.com') {
        let frame = document.querySelector('#retool');
        frame?.contentWindow.postMessage(
          {
            type: "PARENT_WINDOW_RESULT",
            result: JSON.stringify(document.querySelector(e.data.selector)),
            id: e.data.id,
            pageName: e.data.pageName
          },
          "*"
        );
      }
    })
  </script>
</head>
<body>
  <div id="test">Hello world</div>
  <iframe id="retool" src="https://toula.retool.com/p/test" frameborder="0" width="100%" height="100%"></iframe>
</body>
</html>

I hope that helps!

1 Like