Skip to main content

JavaScript

Write JavaScript in Retool.

When building apps in Retool, anything inside {{ }} is JavaScript. You can use it to access variables custom to your app, as well as globals provided by Retool. You can also write custom JavaScript to manipulate data.

For security purposes, all JavaScript runs in a separate iframe, on a different domain. This is to prevent JavaScript injection, such as cross-site scripting (XSS) attacks.

Common Use Cases

Manipulating Data

Because anything inside of {{ }} is just JavaScript, you can manipulate the variables in Retool. Let's say you want to make a string lowercase, just write {{ textinput1.value.toLowerCase() }}. Adding 100 to a value would just be: {{ textinput1.value + 100 }}. Making a date show up in the format you want using moment would just be: {{ moment(table1.selectedRow.date_column).format('YYYY-MM-DD') }} .You can even do more complex things, like map over an array of objects, and pick out one of the fields: {{ query1.data.map(i => i.name) }}.

Because it's all JavaScript, Retool can handle any JSON shape returned by databases and APIs. Just write a quick 1-liner to transform data.

Complex JavaScript

If you want to write multiple lines of code we suggest using Transformers rather than writing them in-line in {{ }}. This is useful if you want to do things like filter, transform, and even join different data sets. Here's an example transformer that takes the results of a database query, filters out for approved users, and returns an array with their credit_amount multiplied by 10:

var users = {{ query1.data }};
var approvedOnly = users.filter(i => i.approved === true);
var amountsTimesTen = approvedOnly.map(i => i.credit_amount * 10);
return amountsTimesTen;

Run JS Code (Perform custom behavior using JavaScript)

You can also manipulate the components in your Retool app programmatically, by Scripting Retool. Rather than doing this in Transformers, you should create queries of type Run JS Code.

For example if you want to iterate over a CSV file and call an API for every row in the CSV, you could do something like this:

// map through every row of a csv file and call an API
return Promise.all(
filepicker1.parsedValue.map((row) => {
return apiQuery.trigger({
additionalScope: {
id: row.id,
},
});
}),
).then((results) => {
return results;
});

See the Run JavaScript page for more about how to write JavaScript queries.

Variables

All of the components and queries have names: for example, textinput1, or query1. And all of them are globally available on the page you're in, so you can refer to them elsewhere on the page: for example, {{ textinput1.value }} or {{ query1.data }}. See our API docs for components or databases for more details.

For example, set the value of a Text component to be {{ table.selectedRow.first_name }}, and the Text component will change based on the selected row of the table.

But we give you other variables too, including libraries like like Lodash (_), and Moment (moment), as well as variables that represent the email of the currently logged in user (current_user), the current URL and its parameters (urlparams), and the browser's localstorage (localstorage).

Exploring objects using the State window

If you want to see a list of all available variables on a page, open the State window from the bottom left panel. From there, you can view all the components, queries, and other global variables available. Anything you can see there can be accessed in Retool.

SectionDescription
Temporary stateThis section lists the variables used in your app and the associated details. Variables enable you to temporarily store your app's state.
ComponentsThis section lists the components used in your app layout, and the associated component details.
QueriesThis section lists the queries used in your app and the associated query details.
GlobalsThis section lists the global variables used in your app and the associated variable details.
Debugging

If code within {{ }} isn't working, try using the State window to debug the issue.