Table Tag Columns - Filling in other Columns

I am new to Retool and successfully built our first app. Impressed with how fast the tables render and the ability to execute stored procedures etc and the render time back has been amazing.

So, in our effort to further see if this is something we can adopt organization wide, been trying to build a basic quoting app. Header - detail table type quote. Ie quote in header table and a table of related rows for the quote lines. Basic stuff and was able to throw it together ridiculously fast, as is the case with a rapid tool like this.

The snag I am banging my head against the wall is what I am hoping is super simple and not looking at this correctly. In the screenshot below, you will see the "Code", for sales item is setup as a tag column so the user can select. I have this properly wired up to query that returns a list of codes. Got the display working correctly. Now when a user selects it, the tag does change. But that tag lookup has other data items I want. Ie it has a Description associated with it and a price. I would need the description to fill in and the default price. If the user has to type that all in, whats the point of the look up.

I have tried many approaches to pull it off, but the table is not letting me manipulate its data in JS. The closest I have gotten is basing the tables data source upon a state variable and I format the data into the state variable as an array. Then I added an event on change to the code (tag) column to update the data in the state variable so that the table shows the change. its alot of extra work for something I think I should be able to just do some JS on the change itself and grab the data from the tags array, but I hit another wall when I realized when I updated the data, the table wasn't seeing the new, say Description I brought in within its changeset. I then wrote some js to manually add this data to the changeset and in the console, says I am doing it, but it seems the table does not recognize a change to its changeset in state unless a user does it.

I cant be the first person that needed a dropdown in a table to fill in other info. Heck, you select say a "user", you would want their dept to fill in, etc.

Can someone with more experience with me hopefully point out maybe where I am approaching this wrong? Trying to avoid a wonky user experience of having to pop up a modal every add or edit of a row. Little reason to have the table there if a modal is required for every edit. In other IDE's, I am able to manipulate the tables with a method of say setValue(). Is there such a thing in retool?

Really appreciate you reading this far and any help or insight that can be offered.


Hi @Wayne_Hopkins and welcome to the forum!

From my point of view you've done what I would have done as well, i.e. having a variable with my data being the data source of my table so that I can update it by setting in the variable's values.

Responding directly to your answer: there isn't unfortunately a method to manipulate tables directly. changeset is read only.

What I don't understand completely is this:

I realized when I updated the data, the table wasn't seeing the new, say Description I brought in within its changeset. I then wrote some js to manually add this data to the changeset

If you're successfully changing price, the same thing should apply for description, right? If not, would you mind sharing your code for this?

1 Like

Hi @MiguelOrtiz ! Thanks for the welcome.

Learning a bunch and enjoying it so far.
Glad to hear I was on the path an experienced dev would have gone down.
I think I settled on either dont fight it and pop up an editor if they want to change the Part Selector, but allow inline editing for description, qty, etc.

The other path would be to write the initial selection on the tag "other columns" to my variable, then when they save, merge both the edits in my variable and the changset into one array, giving priority to changeset (user did it) then make my sql update call. I think this will work as the user selecting a tag will trigger a change in the table and then the key for the row will be logged in changset, even though my other data in the tag dropdown may not be in the changeset.

On the part that I wasn't clear on, I probably wrote that poorly. After updating my variable for the tag selection, I attempted to write to the table changeset and force retool to see this as a user edit. I logged my changeset write and could see the values and it appeared they were applying, but when I looked at state for the table, they were not there. Ie they would select a tag and I would try and write the price and description not only to the variable which is the table source, but also manually add this data to the changset to make the write back easier. Its at that point I figured out those are read only properties.

Here is the code I used if you are curious.

let rowIndex = QuoteLines.selectedDataIndex ;

if (rowIndex === undefined || rowIndex === null) {
    console.log("[GetCurrentLineTemplateInfo] No row is selected yo");
    return;
}

// Get primary key
let primaryKey = QuoteLinesState.value?.[rowIndex]?.SvcQuoteLinesPK;

if (!primaryKey) {
    console.log("[GetCurrentLineTemplateInfo] Primary key missing.");
    return;
}

// Update `QuoteLinesState` 
let updatedData = [...QuoteLinesState.value];

updatedData[rowIndex] = {
    ...updatedData[rowIndex], // Preserve existing values
    Description: GetCurrentLineTemplateInfo.data.Description?.[0] || "",
    Price: GetCurrentLineTemplateInfo.data.Price?.[0] || 0
};

// Apply the updated data back to the state variable
QuoteLinesState.setValue(updatedData);

console.log("[GetCurrentLineTemplateInfo] Updated QuoteLinesState:", QuoteLinesState.value);

// Try to Manually Register the Change in changesetObject
let newChangeset = { ...QuoteLines.changesetObject };
newChangeset[primaryKey] = {
    ...newChangeset[primaryKey], 
    Description: updatedData[rowIndex].Description,
    Price: updatedData[rowIndex].Price
};

// **Try and force Retool to detect the edit by reassigning `changesetObject`**
QuoteLines.changesetObject = newChangeset;

console.log("[GetCurrentLineTemplateInfo] Updated changesetObject:", QuoteLines.changesetObject);

Hi @Wayne_Hopkins,

Thanks for sharing that (I loved the "No row is selected yo" log btw :rofl:)

I hope I'm not oversimplifying here, but the approach I would take is:

  • User edits the tag column
  • You run your Template Info to get description and price
  • You use setIn (instead of setValue) to update your table's data source (a variable), targeting the specific selected row. Something like:

QuoteLinesState.setIn ( [QuoteLines.selectedDataIndex],{ fullchangeset here } )

  • Run a query to update the database with the same changeSet (and using QuoteLines.selectedDataKey for primary Key)

So by doing this you get to update your table's data source (a variable) automatically, by leveraging changesetObjet / or changesetArray, and in the background update your database (rather than updating your database as first action and waiting for the refresh to happen).

Hope this makes sense!

2 Likes

Thanks @MiguelOrtiz

Your guidance was very helpful.

I finally got it all to work, but as is the case with programming many times, I then questioned the path I was on. I realized that this rabbit trail would keep getting longer, for example, what if a user selects a tag/drop down, then wants to back out of change… etc. All stuff that can be dealt with, but I finally backed up and went a simpler route.

I’m allowing my users to do inline editing on certain fields, but if the column value is tied to a specific tag, I pop up a modal and control it there. Ie if the tag is the partID and they try to change description. The end UI turned out clean by adding an event to the description field. I am also then using the modal for double duty and making it my add a part form.

If I end up needing a table that they can truly do what I started this thread with, I may just do something purpose built for my data in react and then make it a custom component.

Until then, trying not to swim upstream and use the UI methodology Retool has designed the IDE around.

It is an amazing product. All have short comings, but they seem to be pouring effort into it, utilize developer feedback and importantly for me, it’s very fast at api calls to sql servers hosted on AWS.

Thanks again,

Wayne

3 Likes