Retool apps 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 Query Editor and select JavaScript 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 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 theblockAllUsers
query to block the user. additionalScope
allows you to pass parameters to your REST query. In this example, it passes thei
variable to theblockAllUsers
.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.
Updated 24 days ago