Create a Grid UI that can capture clicks


I plan to create a grid that is going to be 100x100 cells. I also have a data resource that will map to that grid via X and Y coords. Not all cells will be filled.
Note, if 100x100 is too small i'll just create sections like four 50x50 cells, but a working clickable grid is the goal here.

I looked for a grid and came across this

This is fairly close to what i would want, at least to start with, but i don't quite know how to put this into a custom component.
I'd then need to capture a click on a square so that a query could run to pull up details for that square. Select * from crops where X = {{customcomponent.x}} or something to that effect.

Going through the custom component guide is helpful, but without this grid i am a little snookered at the moment.

Hey @dlbhilbig! Aside from using a list view or a custom component, I think this would be a great feature request. Where you currently stuck, specifically?

@victoria New to react. So i think i need to understand how that custom component works a bit better.

So i'm trying to follow the guide. But i'm not grasping how and where i'd create a loop for a grid. Do i do it in the model window, or in the iframe code.

My thoughts are scattered but my thinking is this:
Each cell, or node, should have a 100/n % width, so... in this case 1% width. Then make the height the same,, or 1% as well and just use a square custom component.
To make really tiny squares usable, i should add an onhover to increase the size to be more certain of a click. Based on the category of data, style the cells so the user can see at a glance what they are dealing with. Then, onclick, send the (X,Y) coords to another component to view/edit details.

I think creating and displaying a grid. After that, with what i'm learning i can see how to get the components to talk to each other. (i hope)

Ah, it's definitely a tricky one that I wouldn't really recommend unless you're familiar with React.

For the custom component itself, the model just holds info that you want to pass from your app to your React code, basically!

For the iframe code itself, that's just regular react/javascript! The only Retool nuances come in when passing the model code into your react/js, so let me know when you get there and I'd be happy to help get that working with you :slight_smile:

As a quick check, would the image grid component be helpful here?

Thats actually a great question. I suppose if I could style it, so that the image size could just be really really small, that might be a way to work through this.

Seems to be an image grid takes a one dimensional array only right?
is there a way to have it work for 2d?

So i flattened the 2d array and voila, I think i have something i can work with.
So this is a portion of the default map with nothing placed on it.
Now i need to gather data from a couple tables which have x,y coords on it, and map those coords to the 0,1,...,9999,10000 th element of this array, and present that data visually.


This is...incredible! Is there anything right now that I can help with? :blush:

Well today I'd like to capture the index of the grid wherever i click.

So if i click on square 3196 i'll be able to see details of what occupies that square.

Ok I think I got the the square being clicked.
Now something fairly hard, at least for my knowledge.
I have a couple resources joined with json query from another solved question from here Combining Data to Get Consumer Sales
Assuming i have some data, i can have something occupy a x,y location. Only one data source can occupy a square: crops.location or furniture.location on the same row of data.
I need to change the image grid to reflect the new data that i imprint onto the default map.

Need guidance on that.

“I need to change the image grid to reflect the new data that I imprint onto the default map”

Hmm! I think I can be more helpful if I can understand your current workflow a bit better :sweat_smile: How are you imprinting this new data? Where is the new data coming from? Are you changing the underlying query?

Ok so the default map is a big 2d array 100x100.
I create all those squares based on the values of that array.
Next I send two queries. One to a Crops database. And the next to a Home database. Both can hold items that will also be put onto this map.

I want to populate this default map with the new data that those 2 new queries have.
So a seed of corn could occupy square 7689, a house could occupy square 8080. I want to see that on the map.
So the final product, should be that big map of squares, with other colours/icons peppered around. If I click on that square i should be able to get the right information to modify it in a separate component.

Cool! And how are the 2 new queries set up so we know which data point goes in which square? Or is that the part you’re currently stuck on?

Sort of how i am stuck
They are both basic select queries with "location" variable for homestead and "tilenum" for the crops tables. effectively they hold the same data, x and y, they were just named differently as we develop the game for some reason.

Besides the unusable squares "U" and "W"ater in the array, a square can hold either furniture or a crop.

Would it be possible to step into your app to take a look around? If so, would you mind DM’ing me a link to your app? If not, happy to work with what you’ve already shared :slight_smile:

our app is locally hosted so I don't know of a way to link to you.

I don't really know what "step into your app" means if that is some lingo i missed out on.

Ah, my apologies! We can log into Cloud orgs once we have permission, but in your case (On Premise), an app export would work as well. App exports don't include query data, so exporting your app with a HAR file would be particularly helpful. If you're not interested, then no worries at all.

Your current app seems a bit more complex than our usual apps that we debug over text, so perhaps coming to an Office Hours session sometime in the coming weeks could be enlightening!

Or if you have any specific questions/error messages, happy to continue trying to troubleshoot here :slight_smile:

The HAR file is huge and seems like it could include a bit of sensitive data. So i am very interested in figuring this out, but want to do so in a way that doesnt expose too much.

I did sign up for office hours this coming tuesday.

Hey there @dlbhilbig! Thanks for attending Office Hours on Tuesday :slightly_smiling_face:

This question has come up before and seems like it might be a good chance to explore how to use React custom components in Retool! This isn't meant to be a complete example but hopefully, it can give some idea of what can be done. A JSON export is included at the bottom to play around with!

We can use the boilerplate that's provided when creating a new custom component. That has a lot of what's needed to get everything connected, and we can just switch out the CSS in the <style> tag and the JSX in the MyCustomComponent function to suit the needs for the grid!

The JSX can be taken largely from the stackoverflow example you linked, just with a couple modifications for Retool.

React lets you dynamically define HTML components to be part of the element you're creating by passing JSX expressions within {}. Here, there's a div that represents the grid, and then all the nodes within it are generated dynamically within {}:

<div id="grid" />
  {/* map function that returns more divs /*}

That's done by mapping over the nested arrays in the dataset, which we'll pass to the model of the custom component so something like:, y) => (
      {/* a nested map function for each node */}

The nodes themselves is where you can add the click handler by passing a function to the onClick property of the element you create. In this case we can use the modelUpdate function which lets us pass data back to the app model which we can reference in the rest of the Retool app. So the onClick handler will look something like this:

() => modelUpdate({ clickedSquare: { x, y }})

Note we're passing a clickedSquare property back that has the clicked coordinates. This can be referenced elsewhere in the Retool app using {{ customComponent.model.clickedSquare }}

We can also pass it a type property to reference with CSS so that it can be colored correctly, since we're mapping over the data being passed in that might be something like


All together it looks like this:

const MyCustomComponent = ({ model, modelUpdate }) => (
    <div id="grid">
      {, y) => (
        <div key={y} className="row">
          {, x) => (
              onClick={() =>
                  clickedSquare: { x, y }

We can then add in the CSS that colors each square based on its type:

    display: flex;
    flex-direction: column;
    display: flex;
    height: min(18vh, 18vw);
    width: min(18vh, 18vw);

    background-color: green;
    background-color: blue;

Again, this is only the start. It's possible to conditionally create img elements instead of div and pass in source urls from the component data, and much more!

Let me know if that's helpful or if you have any questions!