Is it possible to get a list of all components in an application?

Hello!

I've been exploring Retool's functionality and I'm trying to figure out if there's a way to retrieve a list of all the components on a page. This will allow me to dynamically set some values like "hidden" or "disabled". Currently, I can set a hidden value for a specific component by referencing its name and using the setHidden method.

[componentName].setHidden(true);

If I want to apply this value to multiple components, I've considered creating an array of components and then looping through the array to set the value.

const components = [
  { item: confettiButton, type: "button" },
  { item: confettiCheckbox, type: "checkbox" },
  { item: confettiText, type: "text" },
  
];

components.forEach((component) => {
  if(component.type !== "text"){
    component.item.setHidden(true);
  }
})

This approach seems to work, but it becomes inconvenient if I have a large number of components, as I'd have to manually include all of them in the array.

I'm interested in this issue because in the future in our applications, we'd like to dynamically configure parameters such as disabled, read-only, and hidden, based on data from the backend of user permissions for viewing and editing fields.

For example, we could create a global JS script that takes two parameters: an object containing permissions and an object containing all the components on the page. This script would then loop through all the components and, based on the permissions, set them to disabled and read-only. That's why having a list of all components in the app is really important.

there isn't a built-in "retool" way to do this that i've found. you could use

document.body.querySelectorAll('*').forEach(function(node) {
    // Do whatever you want with the node object.
});

I wouldn't really suggest doing this as there are A LOT of dom elements that can make up a single component. this will CHEW threw memory and could take a lot longer to complete than you would think. out of memory errors will crash the browser usually and queries that run to long are aborted/auto failed. best case, you almost double your memory used but it slowly works and worst case your app constantly crashes. at a min I would suggest using something like .querySelectorAll('[role="listbox"]') then storing the query selector and it's hidden value in a database so you only have to torture the browser once when you make changes. careful if you find yourself relying on the classname instead of role however, as these are auto generated and can change from version to version.

personally, I think using something like a State Machine would be a much much better way of doing this. you would basically have a variable named 'isHidden' or something whos value is like a CSV string 'button, listbox, user_group' or an array then for each component for the Hidden value you'd use {{ myVariable.value.contains('button') }} which would hide the component and to show it you just remove 'button' from the string {{ myVariable.value.replace('button, ', '') }} or array and that should trigger a redraw.

Hi @Tatsiana_Shurakova,

Your post made me think about a feature I hadn't really thought about.

If you select several components at once using shift, you can see the option to group them:

image

Once you do that, you actually have a "group" component with its own settings:

It also works like a container, as in you can drag components into the group and it will automatically add them to it, so that kind of saves you the work of adding all of them if you do it as you build it.

So this may be a way of achieving what you're trying to do.

2 Likes

:flushed: how the hell are there enough buttons for me to discover a new one every day?! :rofl:

4 Likes

Good ideas! We also have a feature request for iterating over all components, but it's in our backlog. I'll add your +1!

2 Likes

Thanks for your response! My colleague came across an interesting community post: Can I query retool to ask for a list of retool apps in a certain folder? that mentioned the possibility of retrieving a list of pages in a specific Retool folder for self-hosted instances of Retool. Our goal is slightly different; we want to obtain a list of components within a page rather than a list of all pages. I'm now wondering if this functionality is already available for self-hosted instances of Retool.

would a selector targeting the ReTool custom css of components work better?

like querySelectAll("[class^='_retool']")

1 Like

@Tess, is it possible to export the current app as JSON, while in the app?

Like, could an app have a button that exports it's own JSON representation?

I was thinking, if so, we could easily (In App) export it's JSON and then parse it to get all the component names?

1 Like

:thinking: Very interesting! We don't currently have a utility for exporting :disappointed: