JavaScript in Retool

A quick breakdown of important JavaScript methods for building in Retool

Because JavaScript is such an integral part in building in Retool, we'll be going over specific JavaScript concepts that are particularly important in Retool. If you're brand new to JavaScript/programming in general, there are a few external resources that can help you get started.

There's a lot of overlap between JavaScript Basics and JavaScript in Retool, so if you're already familiar with the basics, feel free to skip this section and jump straight to JavaScript in Retool!

You can think of programming at a high level as just: manipulating data with logic. Retool is all about showing and manipulating your data with drag-and-drop buttons, tables, maps, etc.

So first, we'll cover data in general, how you can represent data, and then how you write logic to show and manipulate that data in Retool.

Data types

Everything in JavaScript is an object, which means it's just a thing with some properties (like a length) and some built-in methods that can manipulate this thing.

🚧

JavaScript object vs JavaScript Object

In JavaScript, essentially all data is referred to as an object. Within this broad category, there is a specific Object data type, which we'll learn about next.

To avoid confusion, I'm going to capitalize Object when we're referring to the specific data type that looks like this {name: "Sparta", age: 9}, rather than the general term object which broadly refers to data in JavaScript.

JavaScript has the following common data types, and all are valid in Retool.

Data typeDescriptionExample
StringA value surrounded by quotes. If a number is surrounded by quotes, it's a string."hi there" , "5" or "true"
NumberA number value. Numbers are also not surrounded by quotes.5
BooleanA true or false value. true and false are reserved keywords that don't need to be (and shouldn't be) surrounded in quotes.true
ArrayA list-like, ordered data structure that can store multiple data types surrounded by hard brackets.[5, 'hi', [1, 0]]
ObjectAn un-ordered data structure with key:value pairs surrounded by curly braces and separated by commas.{name: "Sparta", age: 9, good_dog: true}
Data typeDescriptionExample
JSONJavaScript Object Notation is a data format with properties but no dedicated methods. It's a compact text-based format that is surrounded by curly brackets and contains double quoted strings for keys and values. Single quotes are not valid. Common data type when working with APIs.{ "employees": [{"first_name":"Dwight", "last_name":"Schrute"}, {"first_name":"Pam", "last_name":"Beasley"}]
}

Data Conversion

Managing data types is a fundamental concept that comes up fairly often when manipulating data in Retool. Let's say you want to get the sum of all the prices in your inventory, but the price column is stored as a string in your database. You can use JavaScript data conversion methods to turn those strings into sum-able integers!

MethodDescriptionExampleResult
parseInt("")String → Integer{{ parseInt("3") }}3
number.toString()Number (integer, float/decimal, etc.) → String{{ 3.5.toString() }}"3.5"
['3.5', '3'].map(Number)Array of strings → Array of integers{{ ['3.5', '3', 8].map(Number) }}[3.5,3,8]

Truthy vs Falsy

Because of JavaScript's under-the-hood type casting, all data is either true or false. Numbers can be true or false, words/strings can be true or false. Since true and false are reserved keywords in JavaScript that refer directly to the Boolean type true or false, we say "truthy" or "falsy" as the category that data can fall under. Everything is truthy, except for the following 7 falsy values:

  1. the boolean false
  2. the keyword null
  3. the keyword undefined
  4. the numeric data type NaN
  5. the empty string "" or empty array []
  6. the number 0
  7. the BigInt 0n

Q: Is "0" truthy or falsy?
A: Truthy. It's a non-empty string (truthy).

Q: Is -0 truthy or falsy?
A: Falsy. It evaluates to just 0 (falsy).

Q: Is "false" truthy or falsy?
A: Truthy. It's a non-empty string (truthy).

More on truthy vs falsy in JavaScript here.

Operators

A comparison operator compares its operands (the values before and after the operator) and returns true if the statement is truthy, or false if the statement is falsy.

OperatorNameExampleResult
>Greater than{{ 1 > 1 }}false
<Less than{{ 1 < 1 }}false
>=Greater than or equal{{ 1 >= 1 }}true
>=Less than or equal{{ 1 <= 1 }}true

Logical operators will also return a boolean depending on the truthiness (or falsiness) of the statement, with the exception of the || and && operators which can return a non-boolean, depending on the operands.

OperatorNameDescriptionExampleResult
\|\|ORx \|\| y

Returns x if truthy or else returns y. When used with Boolean values it returns true if either operand is true or false if both are false.
{{ true \|\| false }}

{{ 0 \|\| 7 }}
true

7
&&ANDx && y

Returns x if falsy or else y. When used with Boolean values it returns true if both operands are true or false if one is false.
{{ true && false }}

{{ 0 && 7 }}
false

0
!NOT!x

Returns a Boolean of the reversed truthiness/falsiness of x.
{{ !true }}false
==Equalsx == y

Returns true if the expressions match or false if they don't. Data type is not considered.
{{ 1 == '1' }}true
===Strict equalsx === y

Returns true if the expressions match, false if they don't. Data type is considered.
{{ 1 === '1' }}false
!=Does not equalx != y

Returns true if the expressions don't match, false if they do. The type of data is not considered.
{{ 1 != '1' }}false
!==Strict inequalsx !== y

Returns true if the expressions don't match, false if they do. Data type is considered.
{{ 1 !== '1' }}true

JSON and Data

There are two main concepts at play here: accessing data in an Object and accessing data in an array.

Then, in the JavaScript in Retool section, we can begin thinking about accessing data in an Object in an array in an Object. This is referred to as nested data, which is how Retool queries to your database or API will return data.

Accessing data in an Object

Values in an Object can be accessed using either dot notation (object_name.key_name) or bracket notation (object_name['key_name']). When working with dot notation, property identifies can only be alphanumeric (and _ and $). Dot notation can be limiting (properties can't start with a number), but adding a . after an object will pull up a helpful autocomplete menu in Retool. More on that below!

Here's an example where we first define an Object with the name obj1, then access the value held by the 'greeting' key:

const obj1 = { 'greeting': ['hi', 'bye'], 'number': 5, 0: 1 }
return obj1['greeting']  // this returns ['hi', 'bye']

Retool will offer autocomplete options when writing JavaScript. If you have an Object (which also includes queries or components, like text1) and aren't sure which columns, properties or methods you can access, type .

In this case, dot notation is better than bracket notation since a [ will not bring up the autocomplete menu.

text1. will bring up a menu of all the methods/functions and properties available to text1, along with an example and their typetext1. will bring up a menu of all the methods/functions and properties available to text1, along with an example and their type

getUsers.data. shows a menu of the available columnsgetUsers.data. shows a menu of the available columns

Accessing data in an array

Values in an array can be accessed using the index, or numeric location, of the target. The index always starts at 0, so the first element of an array can be accessed using array[0].

Here's an example:

const arr1 = ['dog', 'cat', 'frog']
return arr1[1]  // this returns 'cat'

JavaScript in Retool

Data in Retool can be manipulated using JavaScript. Data objects have properties that can be referenced. For example, you can access a query's data property via query.data, and a Text Input component's inputted value via textinput.value and a Table component's selected row via table.selectedRow.data.

Example of query1.data , which is an Object filled with arrays, where each array matches a column from the database tableExample of query1.data , which is an Object filled with arrays, where each array matches a column from the database table

Imagine you have a database. This database stores user information—id, name, email and so on. Once you write a SQL query to get this data from your database into Retool, how would you display this data?

You guessed it—JavaScript! You can use JavaScript on the query.data value returned from the query you just ran. We're going to go over a few commonly used JavaScript methods in Retool that would help accomplish this.

In Retool, JavaScript can be written between {{ }} or directly in the JavaScript query type, which we'll get into later. You can also reference the values of Retool components from within {{ }}! More on pulling data from your components here.

This Button Component is using JavaScript in between {{ }} to be disabled when the Checkbox Component isn't checked.This Button Component is using JavaScript in between {{ }} to be disabled when the Checkbox Component isn't checked.

JavaScript in between {{ }} is limited in a few ways. To output a value from a set of {{ }}, it needs to be a self executing function, method, or single value like {{ query1.data.map(row=>row.id) }} or {{ query1.data.id.length }}. You can't run any Retool-specific methods from inside them, like text1.setValue(). (Those Retool-specific methods must be run from a JavaScript query, and complicated if-else statements are easier to manage inside of a Transformer, which we'll get into next.)

You can access and use the output from any query. For example, {{ getProducts.data }} returns the following data where getProducts is a SQL query to get data from a products table in a database.

Here's what getProducts.data looks like:

{
"id":["1", "2", "3"],
"name":["Stucture and Interpretation of Computer Programs","Godel, Escher, Bach","The Seasoned Schemer"],
"quantity":[998001,77777,12563]
}

You can then use {{ getProducts.data }} in a Table Component to display it!

The most common example of {{ }} in action:

The Table Component accepts data as an Object of keys (column names) that point to values (column values).The Table Component accepts data as an Object of keys (column names) that point to values (column values).

Ternaries

Since you can't write if else logic in between {{ }} , but you want to conditionally return data, you can use ternaries. Ternaries are a one-line version of an if else statement (MDN docs here).

condition ? execute if condition is true : execute if condition is false

Since everything in JavaScript is either truthy or falsy, the condition section can be a statement with a comparison operator (e.g. === or >=), or just a plain old object (e.g. table1.data or checkbox1.value). If table1.data exists (has data, and is not empty), the condition will evaluate as true and the first action will execute. See example below!

The ternary in a text component's value checks if table1.data exists, then prints the corresponding text.The ternary in a text component's value checks if table1.data exists, then prints the corresponding text.

JavaScript Queries

JavaScript queries are a special query type in Retool that allow you to write multi-line JavaScript, trigger other queries, download data from your app, set temporary state to store data in your current browser session, etc. Go ahead and read our JavaScript query docs on all the cool things they can do!

One thing you can't do is set table data manually in a JavaScript query. You can return some data, then use the JavaScript query's data in the table's value field, but table1.data = something won't work, nor will something like table1.hidden = true. Components in Retool are generally read only, and are only modifiable with specific methods, found in the Scripting Retool docs linked above (and here).

Quick note: for security reasons, all JavaScript runs in a sandbox.

If JavaScript ran directly on your page, other people in your org could inject malicious scripts to end users, including yourself. To prevent that, we execute all JavaScript in a separate iframe, on a different domain.

That means that inside of your preloaded JavaScript, you won't be able to use jQuery, or other hosted libraries to create your own components, listen to events on the Retool page, etc. You can, however, import libraries! Here is a section of our docs that walk through it. You would need to add it to the libraries section in settings > advanced, then you should be able to get access to the library's methods.

Queries and transformers

Queries are best for calling JavaScript methods (ie query.trigger(), state1.setValue(), etc) while transformers are best for returning a single value or data object.

QueriesTransformers
Format of Retool data (other queries, components, etc) to be used in the querytextinput1.value{{ textinput1.value }}
Runs……when manually triggered…on input change + page load
Executable Retool-specific methods- query.trigger()
- state1.setValue()
- table.selectRow(index)
- modal.open()
- utils.downloadFile(data, fileName, fileType)
- More methods here!
🚫
Return valueDoesn't need a return value, can just be used to run methods listed aboveMust have a return value
How can I access the returned value?{{ query.data }}{{ transformer.value }}

Viewing your data

We're going to take a quick detour and take a look at the ways you can view your data before we get into accessing nested, and more complicated data structures. Viewing your data gives you a birds-eye view of the maze that is nested data, and therefore, makes it easier to access the values you're looking for.

To recap from the beginning, once you successfully query your database, you'll get data back and into your Retool app. This data can be accessed in the data property of the query, like
{{ getPeople.data }}. {{ getPeople.data }} is a nested Object (an Object with Objects with arrays inside).

Retool offers 3 main ways to view this query data: the Query Preview, the Left Panel and the (green) Value Preview.

Query PreviewLeft PanelValue Preview
FormatTableExpandable/interactiveRaw
Data types indicated?🚫
LocationBelow the query after clicking "Preview"Left PanelBelow a value input after clicking in said input
Example
  1. Query Preview

The Preview option will show your data formatted as a table, with easy to view headers/column names and values.

  1. Left Panel (also named the Model Browser)

The Left Panel has information about all of your query, component, transformer, temporary state, global variables (ie current_user or urlparams) data in Retool. You can expand out the object you're interested in to learn more about its data structure.

Each object (in bold) will have its type next to it (in gray) like {} or [], as well as its length in number of items or number of keys.

Each key represents different properties of a query, like error to indicate the presence of an error or isFetching to let you know if the query is still running. It also has the data key, the most important key for queries.


  1. Value preview

This preview shows the raw data. You can even copy the value to your clipboard.

Again, all 3 screenshots are showing getUsers.data, just presented in different ways. Now let's learn how to actually access, and use, this data!

Accessing nested data

This is one of the most important concepts in Retool. We'll learn how to access specific data returned from your database (via queries) so you can start using that data in your apps.

In the example below, the getPeople query has the data key/property (the syntax is interchangeable here), which has the keys first, id and last, which are the column names from our people table. The first key points to an array of first name strings.

{{ getPeople.data }} returns the following data. Again, it's the same as the data we see above in the Left Panel screenshot, just presented differently.

{
"id":[1,2,3,4,5,6,7,8,9,10],
"first":["Myrtle","Nellie","Theodore","Randall","Ralph","Travis","Randy","Christopher","Eula","Jane"],
"last":["Barber","Bowman","Phelps","Hale","Wise","Daniel","Harrison","Allen","Austin","Lewis"]
}

Let's say we want to access the array of ids to use in a dropdown to allow end users to select the user they'd like more info on. To access the array of ids, we can use {{ getPeople.data.id }}.


Data Conversion

There are two data conversion methods that are special to Retool:
formatDataAsArray and formatDataAsObject.

Data from SQL queries are returned as an Object of arrays, where each key is a column name that points to an array of column values.

If you want to show the data as an array of Objects instead (where each Object represents a row), you can use the helper function formatDataAsArray like so: {{formatDataAsArray(sqlQuery.data)}}

MethodDescriptionRetool use case
formatDataAsArrayObject of arrays → Array of Objects

In the context of Retool, it will convert an Object of table column arrays to an array of row Objects.
getActors.data:




{{ formatDataAsArray(getActors.data) }}:

formatDataAsObjectArray of Objects → Object of arrays

In the context of Retool, it will convert an array of row Objects to an Object of table column arrays.
Reverse of above

Array methods

Similarly, whether you need to find the row of data based on the id selected from a Dropdown component, or add new values to the array stored in Retool's temp state (docs here), you'll need to use JavaScript!

MethodDescriptionRetool use case
.lengthReturns the length of an arraygetItems.data.length returns the total number of items returned from the query
.joinCombines elements from an array into a string, with an optional separator (commonly a space) .join 's reverse function is .split , MDN docs here and here
.indexOfReturns the position of the first occurrence of the given value
.includesReturns true or false if an array includes the value passed into the methodgetItems.data.id.includes("1") returns true if an item with id of 1 exists in the items returned from the query
.forEachLoop through each element in an array
.filterReturns a new array with the elements from the original array that match a specified condition
.mapReturns a new array with the results of running a specified function on each element of the original arraygetItems.data.id.map(Number) returns an array of the ids (originally strings) turned into numbers
.pushAdd an item to the end of an array
.concatMerge 2 or more arrays
.reduceReduces the array to a single value by running a provided function for each value of the array (from left-to-right)Useful to sum all values in an array, and can be done in between {{ }} without needing to use a JavaScript query or transformer

Dates

Moment is a preinstalled JavaScript library that helps you manage dates. You can use it anywhere you can use JavaScript with {{ moment() }}.

Most SQL databases store dates in a date or datetime type column, so if you have a string date (like '12/25/1995'), your database will likely reject it. You'll need to convert the string into a proper date type before sending it to your database; this is where Moment comes in.


What’s Next

You made it out! Take a break (you deserve it), and then return to Reschool's homepage to learn more about your next mission.

Did this page help you?