Skip to main content

Web app tutorial: Write custom logic

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 code list and select Transformer. Name it userFirstName and paste return {{ table1.selectedRow.name.split(' ')[0] }} into the editor. This code reads the user's name from the selected row, and then splits out the first name.

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.

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 on the code list and select 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.

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.

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.

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.

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 the tutorial.

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