Listbox.setValue() not working in an async JS query

When you requery a Listbox's data, the selection changes to the the original Default value. So if you select an item and then edit it and requery, you lose the the selection on the item you edited. Expected behavior, so I do a setValue() on it after I update to get the selection back (do same thing on inserting a new record.)

Here is my JS:

(async () => {
  let updatedRecord = await qryUpdateClientsFromForm.trigger()
  let data2 = await qryClientsSelect.trigger()
  console.log(`client_id: ${updatedRecord.result[0].client_id}`) // client_id: 18
  lbClients.setValue(updatedRecord.result[0].client_id)
 })();

I update a record, requery the data source and then select the updated Listbox item. But lbClients.setValue is not working, the first item in the Listbox is still selected.

If I however run this after the query has finished it works:

lbClients.setValue(18)

So there seems to be a timing issue here. Default value ({{ self.values[0] }}) seems to take effect after the setValue() and overrides it even though the requery of the underlying data has already happened.

I have an idea for workaround using a temp var. But I wanted to bring this up as it is unexpected behavior.

Edit: My first workaround idea did not work, but I did find a solid workaround that is way more complicated that I would hope.

Hey @bradlymathews!

This doesn't seem to be reproing for me and cloud which might mean that there's some kind of race condition going on here. Could you share more about your setup for the sake of reproducing the behavior? I'm also curious to know what workaround you came up with!

One other thought is to do something like return the updated value from your update query and then pass {{ updateQuery.data ?? self.values[0] }} as the default value on the Listbox. Then call updateQuery.reset() if the user switches to a new record so that it's not populated with the wrong data. Could that work?

Unfortunately I have already rewired the app with the workaround so I can't test other options or share the setup.

I did think of your workaround, but my setup is more complex in that I have an updateQuery.data and an insertQuery.data and I would need a flag to say which one I last used, which now that I think about it might be a little simpler than what I came up with.

Did even more noodling and here is what I just came up with, which needs no additional temp states or behavior outside of the ListBox itself:

Put this in the Default value:

{{ qryUpdateClientsFromForm.timestamp === qryInsertClientsFromForm.timestamp ?  
  self.values[0] : 
  qryUpdateClientsFromForm.timestamp > qryInsertClientsFromForm.timestamp ? 
  qryUpdateClientsFromForm.data.result[0].client_id : 
  qryInsertClientsFromForm.data.result[0].client_id }}

The only time the timestamps will be the same is on page load when they are both 0. Then I use the timestamps to see which query is the most recent and that is what I set the selection to.

1 Like