Passing data to embedded apps

I have not been able to get data passed from parent window to an embedded app, as per the docs here: Enable public access to a Retool app | Retool Docs

In my case, it's a public app which I tried embedding directly with an iframe and also embedding using the Retool Javascript SDK (for which I cannot seem to find any documentation on).

I believe I have everything setup correctly on the Retool side, as shown in the docs, but whatever I do, the parent window query returns nothing or undefined.

I did make sure that my selector is correct, but what I am not clear on is how the data is supposed to look like in the parent window, and what part of it will Retool actually read.

So, if I specify in Retool a selector of "#mycustomdata", what does Retool get from the parent window? Does it get a DOM object that I am supposed to process further or is it supposed to read the inner text, value of whatever that element is?

Can the element in the parent window that has an id of "mycustomdata" be any element, like a DIV, span, input, etc.? Or should be a specific element formatted in a specific way?

I have read every forum post and whatever I could find on this, so I am really out of ideas right now.

Thanks.

Hi @27shutterclicks,

The data that Retool expects to receive from the parent window should be in JSON format. The JSON object should have a single key-value pair, where the key is the name of the data field and the value is the data itself.

For example, if you are passing a single string value to Retool, the JSON object would look like this:

{
  "myData": "myStringValue"
}

If you are passing multiple values to Retool, the JSON object can be a more complex structure, such as an array of objects or an object with nested objects.

The DOM element in the parent window that has the ID that you specify in the Retool query can be any type of element. However, it is recommended to use a hidden element, such as a div element, to store the data. This is because Retool will not render the element on the page, so it is not necessary to use a visible element.

Here is an example of how to pass data from the parent window to a Retool embedded app using a hidden div element:

<div id="myCustomData" hidden>{JSON.stringify({ myData: "myStringValue" })}</div>

To access the data from the parent window in Retool, you can use the following query:

parentWindow.querySelector("#myCustomData").textContent

This query will return the inner text of the div element with the ID myCustomData.

Hop this helps!

:grinning:

Patrick

O.M.G. Just tell me where to send the beer already! :beers:

Well, that worked, somewhat! I had no idea it was expecting a JSON object, since I don't believe it's mentioned anywhere in the docs or even in the interface of the parentWindow query setup.

I didn't quite get this part:

parentWindow.querySelector("#myCustomData").textContent

Where would I use this inside Retool? It says parentWindow is not defined. Is parentWindow supposed to be the name of the Retool parentWindow query or a JS DOM function?

Anyway, the point is it actually managed to return something based on the selector, which I had to then parse to the value I needed ('myStringValue' in your example):

{{ JSON.parse(myQuery.data).myData }}

On this level, there are some odd aspects on the Retool side, on how it actually treats the data.

In the parentWindow query setup, if a value is provided as placeholder, which let's say in this case would be { "myData": "myStringValue" }, you can access it inside Retool editor using:

myQuery.data?.myData which would output: myStringValue

This is likely because Retool already parses the placeholder value as JSON and because if you "Run" the query, the output WILL be a JSON object:

However, in reality, when embedded, the query will return a string, so the query used inside the Retool editor will never actually work. Based on the following actual HTML element in the parent window:

<div id="mycustomdata" hidden>{ "myData": "myStringValue" }</div>

Checking the query output with a JSON explorer component with its Content set to {{myQuery.data?.myData}} shows the following when embedded and loaded inside the iframe:

image

And if you set the JSON explorer Content to just {{myQuery.data}} you get a string:

image

Hence, the need to parse the output of the data:

{{JSON.parse(myQuery.data)}}

image

However, when you do that, other problems arise in Retool, because now nothing will work in the Retool editor anymore:

And if you try to "fix" this by forcing the placeholder value to be a string, it won't work either because Retool will double down on your fix and turn the placeholder value into a double string:

So the problem is that the code used to test and build things out in Retool will not actually work.

Overall this is both confusing and misleading and it should probably get addressed pronto.


Anyway, many thanks @PatrickMast for your speedy suggestion! Much appreciated!

:+1:

3 Likes

Welcome!

:grinning:

Patrick

@27shutterclicks Hi Andrei, just checking in to see if you were able to solve this. Did you try using JSON.stringify() to avoid getting the "double string" as the result?

Let me know if you have any questions and we can look at this together more closely.

Hi @Francisco_Villarreal , thanks for following up. I believe I got it to work as explained above - which wasn't ideal.

I haven't looked recently to see if anything has changed, but if it hasn't, I suggest that the Retool team takes a closer look at what I described above as it may be blocking or breaking for many users.

If I remember correctly, the way I got it to work was not compatible with Retool's preview value. Basically, if I try to provide a preview value in Retool for testing, it won't work. Similarly, if I adjust the needed so that I test and preview in Retool, it won't work in the actual app anymore.