Hi all. I’ve been trying to figure out how to put the focus on a specific element when I open a modal dialog using uxpShowModal.
I’ve tried focus and autofocus attributes on the element and calling focus() on it either before calling uxpShowModal or in an event handler for the focus event on the dialog itself. I can’t find any evidence of there being a ‘show’ event as there is on panels.
I don’t see any element having focus when the dialog is opened.
You’ll need to clean up TS if not needed
But this isn’t really reliable depending on your dialog contents. In my case 150ms is enough to render all inputs, so it’s already there when it tries to focus
Similar to Karmalakas code. I call focus() of the target element in useRef.
The following code may not work as it is a simplified model, but this is how I achieve it.
// If using React, replace import statement with it
import { h } from 'preact' ;
import { useRef, useEffect } from 'preact/hooks' ;
export const App = (props) => {
const focusRef = useRef(null) ;
// Execute when first called
useEffect(() => {
// If the timing is too early, focus() will be ignored.
// Waiting a little before executing can increase the success rate, but it is not perfect.
setTimeout(() => {focusRef.current.focus() ;}, 300) ;
}, []) ;
return (
<div>
<sp-textfield
ref={focusRef}
value={"0"}
></sp-textfield>
</div>
) ;
} ;
You don’t need to use timeout. Instead you can add listener to “load” event in dialog element. It will trigger focus exactly when dialog is fully loaded so it can be focused.
Thanks all. I’m finding that load is called slightly too early, but might give a better base for a timeout from than the original uxpShowModal? This works nicely for me:
I just tried an event handler for load on the button, but it doesn’t seem to do anything, even with a 500ms delay.
A 150ms delay on load for the dialog is not always enough, but I’ve not seen any failures with 250ms. The downside of that is that you can actually see the dialog draw and then the focus highlighting being applies later. But that’s pretty minor, I think.
I’ve also tried adding two timeouts, one at 150ms and the second at 250ms, which looks a little smoother, but feels distinctly messy!
The messing around with focusList is because I was finding that the command entrypoint that opened this particular dialog suffered even more from multiple invocations than most other triggers in Photoshop. I was getting anything up to a dozen calls to the load event handler without adding that defence around it.
The other interesting thing I noticed is that when I dumped ‘elapsed’ into the console log I was usually seeing times between around 20 and 40ms. But my earlier attempts with a single call to focus sometimes failed with a 150ms delay. I don’t understand JS well enough to even hazard a guess at the reason for that!