Documentation

Welcome to Retool! We're a fast way to build custom internal software.

You'll find the 5 minute demo, quickstart guide, and documentation for each of our connectors and components here. If you've got any questions -- chat with us on the bottom right!

Get Started    Guides

Scripting Retool

Run JS Code (Perform custom behavior using Javascript)

Retool also provides an API for interacting with components and queries through Javascript. To use this feature, select the Run JS Code in the dropdown of resources we have.

Clearing state after running a query

To clear state after a query runs, you can use the following code snippet:

userInput.setValue('');
emailInput.setValue('');
pricingTierDropdown.setValue(null);

Triggering a query

To programatically trigger a query, you can type the following:

query1.trigger()

You can also pass in additional arguments to customize the behavior of the query. Here is an example of doing so:

query1.trigger({
  additionalScope: {
    name: 'hi',
  },
  // You can use the argument to get the data with the onSuccess function
  onSuccess: function(data) {
    console.log('Successully ran!');
  }
})

The additionalScope option allows you to pass to the query additional variables not defined on the global scope. Now, in query1 you may use {{ name}} to refer to the new variable defined by the added scope.

The onSuccess callback is called once the function successfully completes.

Triggering a query for each item in an array

Here is a complete example of doing so:

var rows = [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }];

function runQuery (i) {
  if (i >= rows.length) {
    console.log('Finished running all queries');
    return;
  }
  var data = rows[i];
  console.log('Running query for row', data);

  query1.trigger({
    additionalScope: {
      data: data
    },
    // You can use the argument to get the data with the onSuccess function
    onSuccess: function(data) {
      runQuery(i + 1);
    }
  });
}

runQuery(0);

Returning data

Besides just manipulating components and queries, Javascript queries can also return data. For example, let's say you want to generate a random number inside a Javascript query, and then use it elsewhere. You can do that by first writing some simple JS in the query (let's call the "query" generateRandomNumber):

return Math.random()

Now, when this query is triggered, you can access the number generated via the .data property on the query (so {{ generateRandomNumber.data }}).

Example: firing an API request for each row in a CSV

For this example, we'll try to fire an API request for each CSV, and then also show any errors that occurred along the way for each of the rows in the CSV

1. Uploading a CSV

Create a FilePicker component - and a Table component. We'll use the table to render a preview of the CSV that we upload to Retool - so we'll set the Table's data property to fiepicker1.parsedValue. The FilePicker component autoparses CSVs and JSON files and you can access those values in the parsedValue property.

2. Crafting a query

Now that we have it hooked up, we'll create a query that we want to execute for each row in the table. By default the i property is going to be 0 - our JS Code is going to substitute the i property so that this query ends up executing against different data across the entire run of the query.

3. Add a button and make it execute query1 for each row in the CSV.

We'll create two text components - one to show the current status of the requests (e.g. how many have we processed) and one to show all the errors encountered while processing the CSV. We'll also add a button that will trigger the process.

And then, we'll have button1 trigger the following Javascript query

var rows = filepicker1.parsedValue;
var errors = '';
var total = rows.length;

function runQuery (i) {
  // Update the statusText with the current progress
  statusText.setValue(i.toString() + '/' + total.toString())
  
  if (i >= rows.length) {
    console.log('Finished running all queries');
    return;
  }

  console.log('Running query for row', i);

  query1.trigger({
    additionalScope: { i: i }, // This is where we override the `i` variable from step 2!
    // You can use the argument to get the data with the onSuccess function
    onSuccess: function(data) {
      runQuery(i + 1);
    },
    onFailure: function(error) {
      // Update the errorsText with all the errors encountered
      errors += 'Found error at line ' + i.toString() + ':  ' + error +  '\n\n';
      errorsText.setValue(errors);
      runQuery(i + 1);
    }
  });
}

runQuery(0);

4. Use it!

Since our api endpoint at https://approvals.tryretool.com/api/users/approve doesn't actually exist, all our requests fail and we'll see that we found an error at each of the lines.

Reference: Component and Query Methods.

All queries:

query.trigger(options)

The options is an object with any of the following properties:

{
  additionalScope: any,
  onSuccess: (data) => { },
  onFailure: (error) => { },
}
  • The additionalScope option allows you to override the variables used in the query being triggered.
  • The onSuccess option is a callback that will be called when the query successfully finishes running, with the data of the query as an argument
  • The onFailure option is a callback that will be called when the query encounters an error while running with the error as an argument.

The .trigger function also returns a promise that resolves to the query's .data property.

query.reset()

This function clears the .data and .error property on the query.

Text Component

text.setValue(value: string | number | null)

Sets the text value of the Text widget to whatever is passed in as an argument

Table

table.selectRow(index: int)

Changes the selected row in the table to be the index passed as an argument.

table.selectPage(index: int)

Changes the selected page in the table to be the index passed as an argument.

table.setData(data: any)

Overrides the data of the Table to whatever is passed as an argument.

table.setSort(columnName: string, desc: boolean)

Sorts the table by a column name in a specified direction

JSON Schema Form

jsonschemaform.clear()

Clears all the inputs in the JSON Schema Form

Form

form.clear()

Clears all the inputs in the Form

Tabbed Container

tabbedcontainer.selectTab(index: int)

Changes the selected tab in the tabbed container to be the index passed as an argument.

Modal

modal.open()

Opens a modal

modal.close()

Closes the modal

Temporary State

state.setValue(value: any)

Sets the value of the temporary state variable to whatever is passed in as an argument

Controls

textinput.setValue(value: string | number | null)

Sets the value of the TextInput to whatever is passed in as an argument

checkbox.setValue(value: bool)

Sets the value of the Checkbox to whatever is passed in as an argument

texteditor.setValue(value: string)

Sets the value of the Rich Text Editor to whatever is passed in as an argument

jsoneditor.setValue(value: any)

Sets the value of the JSON Editor to whatever is passed in as an argument

datetimepicker.setValue(value: string | date)

Sets the value of the Date Time Picker to whatever is passed in as an argument

select.setValue(value: string | number | null)

Sets the value of the Select component (Dropdown) to whatever is passed in as an argument

multiselect.setValue(value: string[] | number[])

Sets the value of the Multi-Select component to whatever is passed in as an argument. The argument should be an array since the multiselect's .value property is an array.

radiogroup.setValue(value: string | number | null)

Sets the value of the Radio Group to whatever is passed in as an argument

buttongroup.setValue(value: string)

Sets the value of the Button Group to whatever is passed in as an argument

rate.setValue(value: number)

Sets the value of the Rating component to whatever is passed in as an argument

Filepicker

filepicker.reset()

Resets the filepicker to it's default state (no file selected).

Utilities

utils.openUrl(url: string, inNewPage = true: boolean)

Opens a URL in a new page by default. It can also be configured to open the URL in the same page by passing false in the second argument.

utils.downloadFile(data: any, fileName?: string, fileType?: string)

Downloads a file from a REST Query response. Downloads it using fileName and fileType if possible, otherwise tries to parse it from the URL.

Example

RESTQuery1 fetches from http://somewebsite.com/metrics.pdf

Call utils.downloadFile(RESTQuery1.data) to download metrics.pdf
Call utils.downloadfile(RESTQuery1.data, 'custom_file', 'docx') to download the same file as custom_file.docx

`utils.showNotification({ title: string, description: string, notificationType: 'info' | 'success' | 'warning' | 'error' })

Shows a notification message on the top right corner of the screen. Use this to display messages like error messages after a query fails.

localStorage.setValue(key, value)

Saves a key, value pair to localStorage. You can access the data from localStorage elsewhere by using {{ localStorage.yourKey }}

Scripting Retool


Run JS Code (Perform custom behavior using Javascript)

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.