Saving table with new changes

Hi - I don't know what I'm doing, but I've looked through a bunch of related forum posts (though most seem to describe legacy components) and still can't figure things out.

Desired workflow:

  • User uploads file(s)
  • File name and size appear as a row(s) in a table
  • User manually inputs additional metadata into other editable columns in table (these columns are initially null when the file(s) is uploaded)
  • User's edits to the table are saved (note: this table is just a frontend, without a formal backend - meant as a 'temporary' visual before the files are saved)
  • User clicks a button to actually upload the files with their associated metadata to s3 (metadata determines which folder to upload to)

So far:
My File Input component (addDataFile) has an Event Handler that, upon Change, runs the following query to set Retool variable addDataTableData (which is then used to update the table):

const files = addDataFile.value;
const uniqueFiles = new Map();
files.forEach(file => {
    const name = file.name;
    const size = Math.trunc(file.sizeBytes / 1024);

    if (!uniqueFilesMap.has(name)) {
         uniqueFilesMap.set(name, { name, size });
    }
});

const uniqueFiles = Array.from(uniqueFilesMap.values());
addDataTableData.setValue(uniqueFiles);

My table, addDataTable, has Data source set to this Retool variable addDataTableData, and this works correctly: when files are added, their names and sizes appear as rows in addDataTable.

This table, addDataTable, has another two columns, both of which are editable and of format Tags. Call these two columns A and B. The table has an Add-on that, upon Save actions, runs the following query to update the Retool variable addDataTableData (same one from before, used to update the table):

const tableData = addDataTable.data
const changeSet = addDataTable.changesetArray
tableData.forEach((row, index) => {
     Object.assign(row, changeSet[index]);
})
addDataTableData.setValue(tableData)

This query runs successfully, and I've checked console logs to confirm the variable addDataTableData is updated with the user's manual inputs. However, the table does not reflect these updates correctly (recall addDataTableData is the Data source for the table). Any updates the user makes to column A don't show up at all. Any updates the user makes to column B get added to a newly-created column, also called B (instead of updating the original column B). Furthermore, if the user makes an update to the second row of column B, that update is made to the first row of the duplicated column B, and the second row is kept null.

What am I doing wrong here, and how do I correctly implement table saving (without creating a full Retool table backend)? Really appreciate the help.

1 Like

Hey there @jdjdjd, and welcome to the forum!

First of all, well done for getting this far! Dealing with tables and variables as their data source is not a simple thing.

The approach I would take is using setIn for the variable and update the variable upon each change the user makes. I made a quick video explaining it here.

Here's also the json of the app so you can test it your self
SetIn variable Demo.json (68.2 KB)

The snippets for the setIn event:

Key Path:
[{{ table1.selectedDataIndex}},{{ self.changesetArray.map(obj => Object.keys(obj).find(key => key !== "id"))[0] }}]

Value
{{ self.changesetArray.map(obj => obj[Object.keys(obj).find(key => key !== "id")])[0] }}

Hope this helps!

@MiguelOrtiz Thanks for the explanation, video, and code! Unfortunately, I'm still getting the same exact issue. I tried updating my table with the event handlers you laid out, and I also tried making a brand new table (to ensure none of my queries were still attached or anything): in both cases, I run into the same exact problem. Here's a screen recording: Screen Recording 2025-02-20 at 10.24.50 AM.mov - Google Drive

Hey there,

Try adding a longer bounce, maybe 1500. It seems the changes are being cleared before the variable is set.

1 Like

@MiguelOrtiz Tried it with 1500 for bounce and 5000 for bounce - no dice. The 'change' icon will hang for that amount of time (the little blue triangle in the corner), but then the changes will revert again (or the new Inputs column will be made). Really, really appreciate your help - have been stuck on this for ~2 days.

Ok, so just took out my magnifying glass and detective hat:

  1. The script is not working in your first table because you are not selecting the right variable, it seems the variable name is addDataTableData. So this is the variable you should be changing.
  2. The script is not working in the second demo table because you are not using a variable as data source. You are using the demo data directly, if you create another variable and copy the demo data to it, then it will work.

What seems weird though is that another column is being added, this suggests that you still have other queries being triggered.

1 Like

@MiguelOrtiz For 1, I thought I was setting the correct addDataTableData variable? Previously, when I was using my JS scripts, I also confirmed this was the case in the console. Here's a screenshot again:

Made a brand new table and started from scratch to really make sure no extraneous queries are being triggered. Now, one of the editable columns works, but the other still creates a brand new column (of the same name) with the changes. No idea where this is coming from.

Would you mind sharing a screenshot of your addDataTableData's state showing the data, before and after the change?

Before:

After file is uploaded, before any edits are made:

After file is uploaded, one edit made (to the column that works):

After file is uploaded, two edits made (to the column that works and the one that doesn't):

So seems like the variable is being set correctly. A new "Measurement" column was added to the table though (same name as the original) with the edits made, while the original Measurement column remains null:

@MiguelOrtiz, thanks again for all your help - I really, really appreciate.

Tried making the size column editable, and those edits worked. Changed the size column to be measurement, switched from text to tag field, and it still worked. Then created a new size column that was the same as before. This works now. Maybe this is a Retool bug?

Weird, but glad you got it to work though!

Nevermind - did some other work and refreshed, and the same problem is back. Assuming this is some Retool bug.

first of all thank you for detailed explain I have faced the same problem but now with the help of all your discussion i solved my problem thank you

3 Likes

Hi @jdjdjd,

Thank you for the very detailed documentation! This does seem like a bug on the Retool end for how the table renders its data source when the data source is set to a variable that is being manipulated in real time in the front end.

I can definitely clone the app you shared to reproduce this bug and show it to our UI engineers to get their thoughts on it and if we can fix it or find a workaround.

My guess is that there might be some kind of protection from circular logic creating a dependency loop, but not positive.

I saw your second to last comment and got excited that the workaround might be possible involving column types but that is a bummer that the problem came back.

I think for the short term, the best work around would be to use a form component instead of a table component.

The form component can store the user inputs from the uploaded file and have some dropdown inputs that the user can select akin to how you were looking to implement and editable tags column.

I think the forum component would be a much better fit for your use case. As the table component is build for saving some stateful changes but is better for sitting on top of a DB and using queries to manipulate it.

2 Likes