Option component (drop down) displayed label out of sync with internal state

I have an Option (drop-down) component that works fine most of the time, but then gets into a weird state, where calling .setValue() does seem to change the internal value, but the displayed text no longer changes. The component is query-backed (mapped), from a retool database query with no parameters, and set to 'automatic'.

I've watched it in the debug pane, and the Option component's state indicates that all of the following are changing as expected: .value, .selectedIndex, .selectedLabel, .selectedItem -- and yet the value visible in the page is old and unchanging.

I suspect this has something to do with the following flow:

  1. selecting a record to edit
  2. populating the form (including this component, via .setValue)
  3. changing the value in the component
  4. saving changes to the current record
    5.a reloading the current record (so doing a .setValue on the component again)
    5.b calling .trigger() on the query that populates the component, because the save may have modified the available options
    5a and 5b likely happen concurrently. (Upon further testing, 5b may be a red herring.)

Once it gets into this weird state, the component becomes difficult to use; it does have a value, just not the one it appears to have. No matter how many times .setValue() is called afterwards, it continues to display an old label, while its internal values change correctly. Reloading the app gets back into a fine state.

Cloud 3.155.0 -- unsure whether this was happening on any previous versions.

.clearValue() and .resetValue() did not help.
I tried using a single JS script to react to successful saving by await'ing between the two refreshes, that didn't help.
I artificially added a delay between the two, that didn't help.
I thought at first that if I did NOT .trigger() the query that provides values to the component, the problem went away. Upon further testing, that doesn't seem to be true after all. (Would have been an okay workaround for now, as important changes are relatively rare.)

@philip.williams.healthcareitleaders,

I'm not quite sure I understand what it is you are trying to accomplish. Are you trying to use a select component to choose which database values to edit in a form? Is THIS what you are trying to accomplish?

If so, I have used a state variable to hold on to the changed value and used that in the default value in the Select component, and that worked. If not, could you please send me the exported json for your app so I can take a look?

Also, is there a particular reason you need to use a Select (dropdown) component to select the value you want to change? If you use a Table component, the form component gets automatically populated with the selected Row data, and changes get made to the database and automatically get update in the table without having to use .setValue() anywhere!

Hope this helps! :grinning:

To recap, "the problem" mentioned below is a Select control getting into a weird state where .setValue() calls change its internal state, but the displayed label isn't kept in sync what what the control believes it's showing.

I added a second selection control, and rebuilt it one bit at a time. The problem quickly reappeared, when the control only:

  • had a mapping (that never gets retriggered), and
  • had .setValue() calls when the currently-selected record changed

Looking for options that might be problematic:

  • I had both a Label and a Caption, and I knew my Captions were often null -- removing the Caption mapping didn't fix it.
  • I had the "Show clear button" option enabled; disabling it didn't fix it

I didn't even need to save changes for the problem to appear, I only needed to touch the control, and then navigate to another record. Whichever of the two nearly-identical controls I touched, that was the one that would start having a problem. So it's not about saving, and it has something to do with changing the currently selected item in a drop-down control. But it doesn't happen every time...

After playing with the controls for a while, I think it has to do with how I was manipulating the control itself; the problem did not occur if:

  • I simply clicked the drop-down arrow, and clicked on an item
  • I focused into the control, backspaced whatever value was there, then started typing, and hit enter to select the top item

I did however see the problem start if:

  • I focused in the control, hit shift+home out of habit to select all the text (doesn't work as expected), then backspaced, picked an item, etc.
  • I focused in the control, hit shift+left arrow to select existing text, then deleted it and retyped, or just started typing over the selected text, then hit enter to select the top result
  • I focused in the control, cleared the text by backspacing, typed a little bit, then used arrow keys to select something other than the top result, and hit enter

Once broken, I could get the control back into a functioning state by:

  • clicking its drop-down arrow and clicking on any item (the value is changed, the displayed value now matches, and future .setValue() calls work as expected)
  • clicking into the control, then back out of it (upon blur, the displayed label will change to what it should have been)

I'll see about creating a blank app just to reproduce this issue in isolation, but wanted to give you preliminary feedback on where the bug might be. There are lots of ways of interacting with drop-downs, and it feels like /some/ of them result in the drop-down losing connectivity between the internal state, and its DOM representation (it's not just individual events being missed, because once it's in a broken state, you can make many .setValue() calls and none will be respected visually) -- but it's able to fix itself, so it's not totally dead. It has something to do with having a drop-down with a selected value, clicking into it, and using the text selection/filtering feature to find a new value in the list.

The drop-down is mapped to a query; its resultset is currently approximately 50 items long; it's only "weird" in that one of its items has a null ID and a display text of "None" (this is a hold-over from when this was handled directly in an editable grid, but I'm moving some editing to a separate pane because the table just wasn't ever going to be wide enough; drop-downs in editable tables don't have a "show clear button" option, so providing a None option directly in the mapping was a convenient solution); all other items in the mapped query have unique integer IDs and non-null, unique display text. A few of them start with the same string (e.g. "Sharepoint" and "Sharepoint: more stuff"), which might be relevant to the type-ahead/filtering feature.

I've got it reproduced in an isolated app, I'll send you the ZIP privately. But I wanted to share my observations publicly for anyone encountering this.

It doesn't seem to be related to the null option in the resultset, I can get the problem to reoccur without it. (I've got two side-by-side reproductions, one with and one without a null/None option, and both can behave incorrectly. The one on the right has a dropdown with the "Show clear button" option disabled, to match the dataset it's mapped to.)

It seems to have to do with the type-ahead filtering; the drop-down sometimes remembers the last filter used, and will only display the correct label if that is one of the options it was last filtered to -- so it doesn't totally refuse to change visual labels, it just sometimes is very selective about it, and any labels not in its last-filtered list just won't cause a visual update. (So the fact that I had many labels that started with the same prefix might explain why the issue only sometimes appeared, depending on what text, exactly, I was using to filter the options, and whether that resulted in 1 or several possibilities.) I got it into a state where, after having selected an item, then clicking in the control, it would show a filtered list of options, where the filter was NOT obviously related to the currently-selected item, which speaks to it remembering the last filter.

Steps to reproduce consistently using my example app:

  • click on "Item B2" in the table; the drop-down will change to "Item B2"
  • click into the drop-down field, select+left arrow to select the "2" at the end, backspace; the use arrow keys to select "Item B2" again, and hit enter
  • the dropdown will continue to show "Item B" after the drop-down collapses; it will change to "Item B2" if click away (unfocus)
  • in the table, click on "Item A" -- the drop-down doesn't change to match
  • in the table, click on "Item B2" -- the drop-down changes to "Item B2"
  • in the table, click on "Item B" -- the drop-down changes to "Item B"
  • in the table, click on "Item B2" -- the drop-down changes to "Item B2"
  • (you can continue to toggle between B and B2, and it'll change every time -- but you click on "Item A" or "Something else", it won't sync)
  • in the table, click on "Item A" -- the drop-down doesn't change to match
  • click in the drop-down (focus), and a filtered list appears based on the assumption "Item B" is what you're searching for (weird, given we've changed values several times since we last filtered, the currently-displayed text is actually "Item B2", and the underlying selected value is "Item A", neither of which explain why it's filtering to "Item B")
  • click out of the drop-down (blur) -- the drop-down now changes to "Item A"
  • clicking on items in the table will now work correctly again

There may be other keyboard/mouse interactions that get into a similar state, this was just the one I could most easily describe and reproduce consistently for you.

Reproduce Dropdown Bug.json (32.2 KB)

Ah, I can just upload the .json (but not .zip) version here publicly, it seems?

@philip.williams.healthcareitleaders
I am able to reproduce your bug on your app. The options in the select component are being reset when you enter a value in the select component input that narrows your input choices and this filter overrides the setValue() method. The options are clearly not being reset, even after re-running the query.

I have filed a bug report and will keep you updated on its status. :grinning:

1 Like

@philip.williams.healthcareitleaders ,

There is one thing that you can do to alleviate a major part of this bug. In the Advanced settings (the 3 dots next to the Interaction section), you can check the box "Allow custom values" which will allow the options to be more than what is filtered. This will allow you to select "Item A" even after you have selected "Item B2" and backspaced.