Retool Fundamentals: Lesson 5

Learn how to extend your app's functionality with JavaScript queries and transformers.

As you've learned, anything between curly brackets {{ }} is processed as JavaScript in Retool. This is great for smaller pieces of code, but sometimes apps require more complex logic. This is where transformers and writing custom JavaScript code come in.

Transformers allow you to write reusable pieces of code. They're often used to manipulate data, and you can access the transformer throughout your app using {{ transformer.value }}. Transformers execute their code automatically, and aren't explicitly triggered with event handlers or components.

You can write more complex logic using JavaScript. This allows you to trigger queries and configure components, which gives you more control over how your app works. If you create an app with small pieces of code spread throughout it, you might want to write JavaScript queries to centralize that logic instead.

1. Dynamically display user names

When blocking and unblocking a user, it'd be useful to see their name displayed on the button before clicking it. JavaScript transformers update automatically when the object they reference changes, which means you can write a transformer that reads the user's name from the currently selected row.

Click the + button in the Query Editor and select JavaScript transformer. Name it userFirstName and paste return {{ table1.selectedRow.data.name.split(' ')[0] }} into the editor. This code reads the user's name from the selected row, and then splits out the first name.

Adding a JavaScript transformer

Make sure to save the transformer, then select your Split Button component. Click on the block action and update the label to Block {{userFirstName.value}}. Do the same for the unblock action.

Using the transformer's value to display the user's name

The button now automatically shows the user's first name when you select a row in the table.

2. Add functionality to block and unblock all users

Blocking and unblocking all users uses custom JavaScript to interact with the REST API resource. The JavaScript query identifies which users to block or unblock and then triggers the appropriate query.

Create a JavaScript query

Start by clicking the + button in the Query Editor and selecting JavaScript query. Name it blockAll and then paste this code into the editor.

var rows = table1.data;

const unblockedUsers = rows
  .map((row, index) => [row, index])
  .filter(([row]) => !row.blocked);

let blockIndex = 0;

const blockNext = () => {
  // Notify and quit when finished
  if (blockIndex >= unblockedUsers.length) {
    utils.showNotification({
      title: "Success",
      description: "Successfully blocked " + unblockedUsers.length + " users.",
      notificationType: "success",
      duration: 3,
    });

    // Update table after queries finish

    getUsers.trigger();

    return;
  }

  // Get next unblocked user and unblock them
  const [unblockedUser, index] = unblockedUsers[blockIndex];
  blockAllUsers.trigger({
    additionalScope: { i: index },
    onSuccess: function () {
      blockIndex++;
      blockNext();
    },
  });
};

blockNext();

This code finds unblocked users, blocks them with the blockAllUsers API query (which you'll create in a moment), and then displays a notification with the number of users unblocked. There are a few more things to note:

  • The i variable is the index of the current row. This will be used in the blockAllUsers query to block the user.
  • additionalScope allows you to pass parameters to your REST query. In this example, it passes the i variable to the blockAllUsers.
  • utils.showNotification is a built-in JavaScript method provided by Retool. You can read more about it and other methods in our JavaScript API Reference.

Adding a JavaScript query

Create a query to block all users

Next, create another PATCH query and name it blockAllUsers. Set the endpoint slug to {{ table1.data[i].id }}, and set blocked to true in the JSON body. Make sure to save the query.

Adding a block query that's triggered by a JavaScript query

This query uses the i value passed from the JavaScript query to unblock the appropriate user ID.

By default, queries show notifications after they run. If you're running several queries in succession, you might want to turn these notifications off. To do this, make sure the blockAllUsers query is selected and open the Response tab. Scroll down to Query success and uncheck the Show notification on success box.

Turning off success notifications

With all the code written, select the Split Button component and open the Block all users action. Add an event handler that runs the blockAll JavaScript query when the button is clicked.

Adding an event handler to the block all users action

Add unblocking functionality

You can add functionality to unblock all users by duplicating what you just created and swapping the blocked logic to unblock users. Copy the code below to create the JavaScript query to unblock all users.

var rows = table1.data;

const blockedUsers = rows
  .map((row, index) => [row, index])
  .filter(([row]) => row.blocked);

let unblockIndex = 0;

const unblockNext = () => {
  // Notify and quit when finished
  if (unblockIndex >= blockedUsers.length) {
    utils.showNotification({
      title: "Success",
      description: "Successfully unblocked " + blockedUsers.length + " users.",
      notificationType: "success",
      duration: 3,
    });

    // Update table after queries finish

    getUsers.trigger();

    return;
  }

  // Get next blocked user and unblock them
  const [blockedUser, index] = blockedUsers[unblockIndex];
  unblockAllUsers.trigger({
    additionalScope: { i: index },
    onSuccess: function () {
      unblockIndex++;
      unblockNext();
    },
  });
};

unblockNext();

Wrap up

You've now finished your app and completed Retool Fundamentals.

You can test your knowledge below or see the wrap up page for additional resources.


What’s Next

You've now completed all the lessons for Retool Fundamentals. Continue reading to wrap up the course and recap your progress.