Hi!
Loving Retool.
One thing I couldn't figure out: I have an API resource that returns errors in the form of an HTML page (e.g <html><body>Bad Request - ..details...</body></html>).
I want to display this error in a user friendly format. Specifically, I want to render the HTML.
What's the way to do this?
I tried creating a custom component but couldn't figure out the right way to pass the HTML-as-a-string parameter to the pure JS code such that it will render, and I couldn't find a way to see the generated IFrame code or any console errors.
This did not work in my case. My HTML is, let's say, quite complex.
I get an API response from the Sendgrid and the response is in HTML format. The HTML is the content (body) of the email. I want to render it in Retool so the user does not have to log in to Sendgrid to see what the body looks like.
I've tried the deprecated text component, current component, iframe and custom component, but failed. I've also tried inserting dangerouslySetInnerHTML method in the custom component, but it did not work maybe because my code was wrong. The code for the custom component looks like below.
When I just paste it into the iframe box, it works perfectly fine. As I'm trying to change its HTML code dynamically, I treid passing the HTML content to the iframe through the model. The method I tried but failed was inserting the following codes into the iframe box:
model.content
(model.content)
{model.content} (<- I thought this would work)
{{model.content}}
It seems the model.content that I defined in the model box seems to work only in the context of a certain code.
Admittedly, I am a newbie in the software engineering, but learning to insert the model's value directly or plainly into the iframe box in the custom component could be helpful for other users, too, I guess. Thanks in advance.
Hi, sorry for my delayed comment. I've solved this issue by using the window.Retool.suscribe method. My HTML was a HTML document starting from "<!DOCTYPE html.. " which was taken from Sendgrid email template. I wanted to show the email template in the Retool app.
Below is the Model and IFrame Code that I used. In fact, this is almost the same as the code in the doc: Coding custom components
Is this still a workable solution? I am running into the same issue. I receive an html string from an api that I am trying to display. Works fine when I paste the html directly into the iframe code of custom component but I can't get the html from the query string itself. I tried the above solutions but cannot seem to get it to work. Any suggestions? The query returns a string like this
It looks like you need some extra finagling to get scripts to execute when inserting them using innerHTML. This StackOverflow post has one suggestion of how you might do that which seems to work with some testing.
Code
<script>
function nodeScriptReplace(node) {
if (nodeScriptIs(node) === true) {
node.parentNode.replaceChild(nodeScriptClone(node), node);
} else {
var i = -1,
children = node.childNodes;
while (++i < children.length) {
nodeScriptReplace(children[i]);
}
}
return node;
}
function nodeScriptClone(node) {
var script = document.createElement("script");
script.text = node.innerHTML;
var i = -1,
attrs = node.attributes,
attr;
while (++i < attrs.length) {
script.setAttribute((attr = attrs[i]).name, attr.value);
}
return script;
}
function nodeScriptIs(node) {
return node.tagName === "SCRIPT";
}
</script>
You might try copying the provided script above as a top-level script tag in your custom component and then doing:
window.Retool.subscribe(function(model){
const body = document.getElementById("body");
body.innerHTML = model.body;
nodeScriptReplace(body);
})
That worked perfectly! Thank you! It would be a nice feature for an easier interface to insert html from external sources into the html component or custom component.
Ah spoke too soon. It displays the html when the code is first put in the iframe but doesn't update and goes blank soon after. I'm pretty new to webdev so not really sure where to go but I will read up and update if I can figure something out.
UPDATE
The solution displays the figure when first put in the custom component but goes blank when entering preview or running a new query. I found a cleaner implementation on the same post that works in the same manner.
This seems to work. The componenet was only rendering when I made changes in the script editor for some reason. Adding the subscribe portion to the top level script seemed to fix though I am not sure why.