Hi there, I have a basic table with two columns: "A" and "B".
A is a boolean column (default: false), represented by a checkbox.
B is an integer column whose default value is null.
When the user ticks column A, then column B must be populated with the row number. Whenever column A is unticked, the value of column B must be changed back to null.
Could you please tell me the easiest / best way to achieve this?
Also, if in a given row column A is ticked, I want column B at that row to be editable. If A is not ticked, then column B should not be editable.
What I tried (but I'm not married to this approach):
I'm trying to attach a handler to the "cell changed" event on my table, but oddly enough, I can't reference the table itself from the handler.
You can use current row within the "mapped value" field within your B column and use a terniary to return different values, e.g. {{ currentRow.a === true ? currentSourceRow.id }} (if by Row number you mean the index, then you can use "i".
You can do the same and make the "Editable" field dynamic:
I tried it, but it doesn't work. In the mappedValue field I have access to currentSourceRow, but not currentRow.
Keep in mind that, when the checkbox in col A is ticked, that change is not synchronized with the db (nor it should be). It's just a local change to the table.
When the checkbox is ticked, the local version of column B must be populated with the appropriate value. But then, it is up to the user to synchronize the data with the db.
When I tick the checkbox, currentSourceRow does not change, and therefore, column B is not updated.
I have a couple of questions about the function of this use case. It seems like what you actually want is to use the Multi-Row selection properties of the table. When you enable this and select the generated checkbox for the row, a property of the table called selectedRowKeys is available as an array of all of the row numbers for the selected rows. There is also selectedDataIndexes.
Either way, you could then tie the edit function of any column to the this array by using the i reserved index property for the column:
{{ table2.selectedDataIndexes.filter(index => index >= 0).includes(i) }}
ETA: I filter for indexes greater than or equal to 0 because I don't trust the table component to not return a -1 value for the "select all" toggle. It used to be wonky and this rules it out regardless of if it gets fixed.
No, that's not what I'm trying to do, but thanks for your reply. I don't want to allow item selection on my table (single or multiple). I want that, when you change column A's value to true (hence the checkbox), column B gets populated. And when column A is unchecked, column B returns to no value.
Although this might be something which you could achieve I believe you are attempting to use the Retool table slightly outside of its intended purpose.
Regardless... Here is how you can utilize the changesetArray of a table to determine whether or not 1) another column is editable and 2) how to set a value in that column when the row has a changed checked state:
A column value statement to display stuff when another column is checked (id is the PK on the row):
Hey @Wei_Chen! Thanks for stopping by office hours this morning.
To summarize, there still isn't a particularly simple solution for updating one column based off of edits made to another column, given that staged edits are stored in the table's changeSet and can't be easily mapped to another column. The implementation previously suggested by @pyrrho is still the best way to do this.
One workaround that I have suggested in the past is to essentially replicate the contents of the backing database as an app variable and use it as the data source for your table. You can then bypass the changeSet and apply all edits directly to this variable, thus allowing you to immediately map changes in one column over to another.
I understand that this is one part of the table component that might feel a little over-engineered, given how simple it would be to accomplish the same task in a spreadsheet. The complicating factor, in this case, is that a Retool table is synced to a backing database and we need to maintain in-progress edits as a distinct entity.
Regardless, I'll take your feedback to the team in order to help steer the direction of future development! Don't hesitate to let us know if you have any follow-up questions or comments.
Thanks for your reply. I try to follow your workaround by putting all the data in a Javascript array object. The table data is loaded from the array. But how do I by pass the changeSet and apply the edits directly to the array? The table doesn't automatically update the array, does it? or I miss something?
No, unfortunately not - this particular setup requires a bit more manual configuration. You would have to set up an event handler that updates the array variable the same way that you would normally write a query that updates your database.
I'd probably use the "Save Action" event, but that does mean you'd need to trigger an actual update to your database somewhere else. The setData method that you're referencing was defined on the previous generation of the table component but hasn't yet been implemented for the newer one. The feature requests exists, but the current workaround is the state variable middleman that you've already implemented.
Is there a way to trigger the Save Action without user interaction (clicking the save button)? Basically I want to this looks like a normal spreadsheet where updating one cell will automatically updating another cell without extra user interactions.
In that case, you'll probably want to define an event handler on the "Change cell" event that updates the state variable. If that same variable is set as the data source for your table, everything should update in real time!