Nested evaluation of {{ foo }}

I have an HTML component that is displaying some help text. Inside that text are references like this:

To do foo press the <b>{{bar.text}}</b> button.

When this is evaluated {{bar.text}} is replaced by the label from the component named bar. Nice.

I then decided it would be good to put this help text into a database. Now the content property of the HTML component looks something like this:

{{query99.data.text[0]}}

And when this query brings back the string

To do foo press the <b>{{bar.text}}</b> button.

What happens is {{bar.text}} is not evaluated and transformed into other text. The string {{bar.text}} is displayed. Not good.

Is there a workaround for this?

I think that's what I'd expect to happen, your query is returning some text, it's not returning some code to be executed by the Retool app.
It would appear that you'd want to "eval" that statement to make it run and extract the label. I'd suggest that's not the safest or best approach, though (eval rarely is), but you may find that works.

If I can ask - I guess that if the help is in the database then the label on the text component is also coming from the same source?
Maybe your query should return the label and help text and use the component id as its key - this would be much cleaner and also cut down on the number of lookups your app is having to do

Eval is definitely the right idea. I looked for it in utils but did not find it. Is it there, somewhere?

As for security issues the eval would not be on javascript coming from some random source. It's coming from a source totally owned by the app. My toy example is not the only one. The {{string}} in question can easily be some other data that is generated in Retool by other business logic. Pushing the string composition off onto some other place (the database) could work but it certainly wouldn't cut down on traffic to the database.

Well I didn't know eval was built-in to Javascript. :roll_eyes: But there it is. And in the Retool IDE there is even a red squiggle and a warning about it being potentially unsafe.

But sadly it does not solve my problem because the "eval" needed is over a giant block of HTML and the special flavor of Javascript inside {{ }} which is a Retool thing. Retool knows how to look at the HTML inside an HTML component, find the {{ }} and eval what is inside in the context of the application runtime state. When I call javascript eval on this string it just dies on the first HTML token and throws a "this isn't javascript" error.

The solution I thought might work is to obtain the full block of HTML (including the {{stuff}} ) in a local variable and then do a .setValue() operation on the HTML component. But the HTML component has no such operation.

I could test that theory with some other plain text component that does have a set value function, but I need the final destination to be HTML in this case. I can type {{foo}} into the HTML component and it will eval {{foo}} at runtime and replace it with data. But I cannot push data into the HTML component at runtime.

You can always pass the value of a JS query or transformer to your HTML component and then do any necessary calculations there! Those will be calculated at runtime and as they're recalculated the component will update with the latest value.

Another idea is that you can parametrize the string you're storing in the DB and then use replace to pass in values from your app. For instance, if you have "To do foo press the <b>$1</b> button." in your DB you can pass {{ query99.data.text[0].replace("$1", bar.text) }} in your HTML component. This stackexchange post might also be an interesting read for how to replace multiple values.