S
SolidJSโ€ข15mo ago
nikivi

Why autofocus on input element not work with solid second time

I have this code: https://github.com/nikitavoloboev/kuskus Here I do conditional render of NewTodo: https://github.com/nikitavoloboev/kuskus/blob/main/src/pages/Today.tsx#L14 Here is input with autofocus https://github.com/nikitavoloboev/kuskus/blob/main/src/components/NewTodo.tsx#L37 For some reason when I create a first todo, autofocus works but second time it does not. Even though solid mounts it twice. onMount runs twice. What is going wrong? Is there a better way to achieve bringing focus to input box?
87 Replies
Max
Maxโ€ข15mo ago
Cant really explain in too much depth but I just dont think autofocus html attribute works well with non static sites. And different browsers do different things. I suggest getting a ref and focusing in onMount
thetarnav
thetarnavโ€ข15mo ago
we have simple autofocus helper in solid-primitives that helps here
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
GitHub
solid-primitives/packages/autofocus at main ยท solidjs-community/sol...
A library of high-quality primitives that extend SolidJS reactivity. - solid-primitives/packages/autofocus at main ยท solidjs-community/solid-primitives
nikivi
nikiviโ€ข15mo ago
reading docs it seems that this should work ๐Ÿค” never used attributes with : inside kind of odd looking or its expected and I should ts-ignore it?
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
reading through root readme maybe i have to do something to make it work
nikivi
nikiviโ€ข15mo ago
GitHub
solid-primitives/packages/autofocus at main ยท solidjs-community/sol...
A library of high-quality primitives that extend SolidJS reactivity. - solid-primitives/packages/autofocus at main ยท solidjs-community/solid-primitives
nikivi
nikiviโ€ข15mo ago
i think i followed this part correctly
thetarnav
thetarnavโ€ข15mo ago
ts tree shakes the directives as they are only strings So you can use them right after import do that ts won't touch them or use a ref and the directive as a function. I guess the docs should mention it. I'll correct it.
nikivi
nikiviโ€ข15mo ago
im bit confused what you mean i know tree shaking is removing non used code when making builds directives i googled now
nikivi
nikiviโ€ข15mo ago
directives ยท WebPlatform Docs
The following table lists JavaScript directives. A directive is a token that adds certain syntactic and semantic restrictions.
nikivi
nikiviโ€ข15mo ago
still confusing
So you can use them right after import
i thought im doing this
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
oh I see so directives are i guess functions for attributes thats neat til
thetarnav
thetarnavโ€ข15mo ago
lol actually youre better of not using directives ever xd
nikivi
nikiviโ€ข15mo ago
why? too hard?
nikivi
nikiviโ€ข15mo ago
GitHub
solid-primitives/packages/autofocus at main ยท solidjs-community/sol...
A library of high-quality primitives that extend SolidJS reactivity. - solid-primitives/packages/autofocus at main ยท solidjs-community/solid-primitives
nikivi
nikiviโ€ข15mo ago
trying this approach now with ref i guess
thetarnav
thetarnavโ€ข15mo ago
to many quirks - ts tree shakes them - the types for them are declared globally, so ts will allow you to use them even if they are not available in the same file - cannot be used on components there is probably more if you ask fabio
nikivi
nikiviโ€ข15mo ago
so createautofocus?
thetarnav
thetarnavโ€ข15mo ago
for now I'll adapt autofocus to work with ref as well
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/NewTodo.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
trying this that fails im confused where that func should go maybe onMount or something docs just seem to imply i can add it anywhere
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
btw unrelated issue but maybe you know @solid-primitives/keyboard for some reason i guess this insane bug when I try to delete
thetarnav
thetarnavโ€ข15mo ago
thats pretty much the case
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/Page.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
even though I only activate it once ๐Ÿ˜• apparently not everywhere
Max
Maxโ€ข15mo ago
I really never enjoyed the directives thing either, its cool idea but not smooth experience
nikivi
nikiviโ€ข15mo ago
unless i missed something
const [ref, setRef] = createSignal<HTMLButtonElement>()
createAutofocus(ref)
const [ref, setRef] = createSignal<HTMLButtonElement>()
createAutofocus(ref)
i just did this in component
<input
ref={ref}
<input
ref={ref}
then added ref to the input
Max
Maxโ€ข15mo ago
normally i do ref={ref=>setRef(ref)} here seems you're setting accessor to ref value
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
doesnt like that guess due to naming will try change const [ref, setRef] = createSignal<HTMLButtonElement>() or rather its due to type fk my bad ๐Ÿ˜„ const [ref, setRef] = createSignal<HTMLInputElement>() ok autofocus works
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
but this bug is so strange, delete just does this insane cascade thing
thetarnav
thetarnavโ€ข15mo ago
youre subscribing to todos()
nikivi
nikiviโ€ข15mo ago
oh in effect my mental model of effects was that whatever signal gets used inside effect gets subscribed to i guess thats what you mean opened another issue for the effect but for this ref issue, there is another issue where it does auto focus on creating first NewTodo but when you create second one it doesn't autofocus to it this is strange because I would think the ref would be different
<Show when={newTodo()}>
<NewTodo />
</Show>
<Show when={newTodo()}>
<NewTodo />
</Show>
i.e. here is where NewTodo gets rendered
createEffect(() => {
if (event()?.key === "Enter") {
setTodos([
...todos(),
{
id: Math.floor(Math.random() * 100 + 1),
title: input(),
done: false,
},
])
setNewTodo(false)
}
})
createEffect(() => {
if (event()?.key === "Enter") {
setTodos([
...todos(),
{
id: Math.floor(Math.random() * 100 + 1),
title: input(),
done: false,
},
])
setNewTodo(false)
}
})
when return is pressed setNewTodo is set to false so when it gets set to true again that should be new component I would think but @solid-primitives/autofocus does not like it ๐Ÿ˜ฆ
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
oh and i tried to do it as they do in docs
nikivi
nikiviโ€ข15mo ago
GitHub
solid-primitives/packages/autofocus at main ยท solidjs-community/sol...
A library of high-quality primitives that extend SolidJS reactivity. - solid-primitives/packages/autofocus at main ยท solidjs-community/solid-primitives
nikivi
nikiviโ€ข15mo ago
well i guess i have signal in my case
thetarnav
thetarnavโ€ข15mo ago
so it works initially, but not when the target is updated? I'll need to do some experiments here.
nikivi
nikiviโ€ข15mo ago
yes you can clone my repo to replicate
nikivi
nikiviโ€ข15mo ago
GitHub
GitHub - nikitavoloboev/kuskus: Fast todo app
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
it adds the entry but doesn't autofocus first one is ok could be I am using it wrong
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
strange error I did as they have in example i think
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/NewTodo.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
although in my case i don't know where to put setRef i have just one input in example there is 2 inputs
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
also have type error which is odd as i also have input and stackblitz is input ๐Ÿค”
thetarnav
thetarnavโ€ข15mo ago
I've made an update to allow it to be used with ref easier, so you might update
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
doesn't work still but no error 2nd time it doesn't focus @thetarnav do you have an idea of why my code breaks? I read through the stackblitz you shared it seems to be very much the same only in my case I actually create new inputs it seems the issue is that the component doesn't get unmounted or something, its confusing
thetarnav
thetarnavโ€ข15mo ago
new inputs are created in the demo too so I'm not sure
nikivi
nikiviโ€ข15mo ago
wait i think i need to pass setRef perhaps like in my case its not used
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/NewTodo.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
export const createAutofocus = (ref: Accessor<HTMLElement | FalsyValue>) => {
createEffect(() => {
const el = ref();
el && setTimeout(() => el.focus());
});
};
export const createAutofocus = (ref: Accessor<HTMLElement | FalsyValue>) => {
createEffect(() => {
const el = ref();
el && setTimeout(() => el.focus());
});
};
thetarnav
thetarnavโ€ข15mo ago
the demo shows two different methods, you can use either
nikivi
nikiviโ€ข15mo ago
oh so im using the 2nd one i think correctly well exactly as in demo but for me it only works on first time
thetarnav
thetarnavโ€ข15mo ago
yeah I'm not sure I have to be missing something
nikivi
nikiviโ€ข15mo ago
el && setTimeout(() => el.focus()); this line is not too clear for me like it sets focus insantly it seems is there perhaps another way to set focus on components in solid? going to try 1st method although that one failed too i remember
thetarnav
thetarnavโ€ข15mo ago
.focus is a browser api I would just try using it directly and see when it works and when it doesn't like, reverse engineering the directive
nikivi
nikiviโ€ข15mo ago
<Show when={newTodo()}>
<NewTodo />
</Show>
<Show when={newTodo()}>
<NewTodo />
</Show>
I have a feeling this is breaking it like it doesn't like this Show I am not using the directive I think it seems to me like the solid component never dissapears although it should i checked with onMount it gets called twice so i'd think the .focus() would work second time too trying this now
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
ah its a function ok still fails
onMount(() => {
ref()?.focus()
})
onMount(() => {
ref()?.focus()
})
yea it doesn't like this too doesn't even work on first time
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
is the dev folder like an example for autofocus in solid-primitives as it looks diff to stackblitz you shared createAutofocus(() => ref); // Or using a signal accessor. another thing is here in example
nikivi
nikiviโ€ข15mo ago
or wait nvm thats fine yea i don't even know where to start debugging i tried to do raw .focus() it didn't even work onMount
thetarnav
thetarnavโ€ข15mo ago
try ref={el => onMount(() => setTimeout(() => el.focus(),200))}
nikivi
nikiviโ€ข15mo ago
nikivi
nikiviโ€ข15mo ago
didn't work ๐Ÿ˜ฆ
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/NewTodo.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
did it like this maybe you meant it differently I have the wildest thing
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/Page.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
this works but if I activate from button it doesn't trigger on second time ๐Ÿค” its so weird something about pressing the button
nikivi
nikiviโ€ข15mo ago
GitHub
kuskus/ActionBar.tsx at main ยท nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviโ€ข15mo ago
button onClick does same thing though
onClick={() => {
if (!newTodo()) {
setNewTodo(true)
}
onClick={() => {
if (!newTodo()) {
setNewTodo(true)
}
tried this too its really strange, like with hotkey and button I do same thing set the signal state only from hotkey it works amazingly well but from button it fails on 2nd activation
nikivi
nikiviโ€ข15mo ago
GitHub
autofocus: Does not work on component 2nd time even when using API ...
Using latest version of @solid-primitives/autofocus. I am trying to use it in this project. In theory I am doing exactly the same thing as the docs say. Here is the component. Ref and createAutofoc...
nikivi
nikiviโ€ข15mo ago
ok opened an issue, maybe someone knows
thetarnav
thetarnavโ€ข14mo ago
I've added these console logs to NewTodo: it appears that on the second time you create a new todo it's getting disposed immediately, even though it stays on screen so autofocus doesn't fork because it happens in onMount which never runs
thetarnav
thetarnavโ€ข14mo ago
But this only happens after clicking the plus button. Pressing n works fine
thetarnav
thetarnavโ€ข14mo ago
GitHub
Fix autofocus and keyboard shortcuts by thetarnav ยท Pull Request #1...
I think that the createEffect in src/components/NewTodo.tsx was causing some state change right after mount, causing the component to be disposed of immediately. don't know why exactly, the sta...