Return focus after refreshing Grid row (Vaadin 23)

I have a scenario where the user clicks on a cell (containing a TextField) in a Grid and then uses a keyboard shortcut to launch a Dialog; when the Dialog is closed, I want the focus to return to the Component that held it prior to launching the Dialog.

I initially came across this bug that led me to add “overlay.restoreFocusOnClose = true” into the JS that runs in the attach listener, and that works in the base case. However, there are certain scenarios in which the Grid row gets refreshed based on the user’s actions within the Dialog, and when that happens the focus gets lost - presumably because the previously focused TextField has been replaced when the row was refreshed.

Fortunately I know the element id of the TextField (it is the same before/after refresh) and I have a JS function to place the focus on that element, but I still can’t get it working in the refresh case - I suspect because it is getting called before the refresh completes. Is there some event I can listen on to make sure I call my JS function after the refresh completes? I tried tapping into DataProviderListener (among other things) but I’m not seeing any way to trigger specifically on the completion of the refresh.

Hi Ryan!

I would re-focus it with Java API instead. So add a focus listener ans store which dto/textfield is currently focused and then manually focus it when returning the component in your grid. I think I have done something similar myself before, but I remember focusing is not necessarily enough as the component might contain some unsaved changes you don’t want to get lost. Thus you probably want to always return the same instance for the same DTO.

I think/guess that the Dialog is not critical here, but refreshing the Grid. Created this kind of quick and dirty example how I’d do it. I hope this helps:

https://gist.github.com/mstahv/617f46be0606527008e6d4b29b0454ec

(Note, that if the DTOs after refresh are not the same instances, this (weakhashmap based solution) might not work. You could then use e.g. some cache with reasonable size and have a proper equals/hashCode for your DTOs)

Thanks for the quick response Matti! I got tied up with a couple other things and haven’t had the chance to try this just yet, but will update you as soon as I do. My ValueProvider is defined in a separate class and used elsewhere in this and related projects, so I won’t be able to follow your implementation exactly, but I have some idea of how/where I can make a similar change to hopefully get the same result.

Hey Matti, I’m getting the desired behavior now by following your strategy of putting the focus() call inside the ValueProvider. Thanks so much for your help!