Pass arguments to javascript object

In the Best Practices with JavaScript they recommend centralizing logic in javascript code.

I have a perfect use case for this but I'm not sure how to go about it. I have several transformers which currently repeat a lot of code.

I want to centralize this code in a javascript code object. There needs to be some variability though, defined in the transformer, e.g.:

  1. the data to be processed
  2. the columns to process

On a basic level, how can I go about using the javascript object as if though it were a function within a React app? I want to be able to pass arguments through to it.

Hello @amir_insighta and welcome to the forums!

I believe what you are looking for is the additionalScope object which can be used to send variables and other options to your queries:

I anchored the link above to the Trigger a Query section of the docs where you can see some basic usage with passing data to a query.

For your specific case, it sounds like you are going to need to pass the data either from a currently displayed table (or its underlying data source) and possibly some indicator of what code path you need to traverse.

Hi @pyrrho , I tried using additionalScope but I can't seem to get it to work. Following the documentation I have a very simple POC that is supposed to add two numbers together.

First, I have a JS query, called mathUtils

// Define a function to add two numbers
function addNumbers(a, b) {
  return a + b;
}

// Export the addNumbers function
return {
  addNumbers
};

then I attempt to trigger it while passing a couple of variables as arguments using the additionalScope(). I do this in a transformer.

// Define the numbers to add
const num1 = 5;
const num2 = 3;

// Trigger the `mathUtils` query to ensure the function is available
mathUtils.trigger({
  additionalScope: {
    a: num1,
    b: num2,
  },
  onSuccess: function(data) {
    // Access the utility function from the returned data
    const { addNumbers } = data;

    // Use the utility function with the provided numbers
    const result = addNumbers(num1, num2);

    console.log("Addition result:", result);
    return result;
  }
});

The screenshots show my error message and configuration. The error message indicates that the transformer cannot find the mathUtils JS query. Am I missing something in this implementation?


Hi Amir, @pyrrho is right about how you should be using JS queries.

They are not really designed as function libraries. As far as I am aware you can't just export a function the way you would with say ESM exports.

Retool doesn't seem to allow functions as first class objects so you can't just pass them around.

An easy way to use your function would be to put it in the global app space. (Go to app settings on the left hand side of the IDE).

The closest to a working result in your example might be:

function addNumbers(a, b) {
  return a + b;
}
return addNumbers(a,b) // can call the function but cannot return it


mathUtils.trigger() 
   ... 
     onSuccess: 
       console.log('the value is ' + data)

Hope this is helpful!

This sounds promising! However, I don't quite understand what you mean by "global app space".

Looking at the left side of the IDE the closest I seem to find is "Preloaded JS". Is that what you are referring to? Below is a screenshot what I am seeing.

If so, I am not sure how to integrate the code you shared with the pre-existing snippet already present.

Hi Amir, sorry about the slow reply.

Yes you found the right area with the Preloaded Javascript.
Mostly you will use this for function definitions, not actual script code.

That means you don't need to trigger() anything, simply call the function by its name in your code:

// Define the numbers to add
const num1 = 5;
const num2 = 3;

// Use the utility function with the provided numbers
const result = addNumbers(num1, num2);

console.log("Addition result:", result);

For example, put this in an event handler:

Also, I'm not totally sure but I think they might have deprecated the window.retool namespace.
I can't access any objects in that which means .queries does not work.
I always just call query1.trigger().
Let me know if you got that or window.retool.data to work so I can try it!

With your latest code I would probably (depending on how the rest of the app is structured) do these things:

Make containerFilterValues a state variable so you can access it anywhere via containerFilterValues.value

Keep trigggerBaseQueryWithFilter in the preloaded JS. I would use the syntax
function trigggerBaseQueryWithFilter(filterValue) ... rather than a const and an anonymous function.

I wouldn't add an eventListener to the window unless absolutely necessary.
Generally you would make a JS query for containing the for (const filterValue ... and set it to run on page load.

I find Retool to be pretty confusing about where it would like me to put code, so that the app doesn't become a complete mess. If anyone like @pyrrho can help with best practices that would be great.

Good luck!

3 Likes

@stewart.anstey you are a legend! You showed us two ways to centralize:

  • JS functions (Preloaded JS)
  • variables (variable object)

Both worked brilliantly. You have saved us hundreds of lines of code. I marked your latest answer as the solution.

Thank you for taking the time and giving such clear responses!

2 Likes

You are very welcome thanks for the nice feedback!

1 Like