S
SolidJSā€¢2y 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ā€¢2y 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ā€¢2y ago
we have simple autofocus helper in solid-primitives that helps here
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
reading through root readme maybe i have to do something to make it work
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
i think i followed this part correctly
thetarnav
thetarnavā€¢2y 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
nikiviOPā€¢2y ago
im bit confused what you mean i know tree shaking is removing non used code when making builds directives i googled now
nikivi
nikiviOPā€¢2y ago
directives Ā· WebPlatform Docs
The following table lists JavaScript directives. A directive is a token that adds certain syntactic and semantic restrictions.
nikivi
nikiviOPā€¢2y ago
still confusing
So you can use them right after import
i thought im doing this
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
oh I see so directives are i guess functions for attributes thats neat til
thetarnav
thetarnavā€¢2y ago
lol actually youre better of not using directives ever xd
nikivi
nikiviOPā€¢2y ago
why? too hard?
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
trying this approach now with ref i guess
thetarnav
thetarnavā€¢2y 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
nikiviOPā€¢2y ago
so createautofocus?
thetarnav
thetarnavā€¢2y ago
for now I'll adapt autofocus to work with ref as well
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/NewTodo.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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ā€¢2y ago
thats pretty much the case
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/Page.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y ago
even though I only activate it once šŸ˜• apparently not everywhere
Max
Maxā€¢2y ago
I really never enjoyed the directives thing either, its cool idea but not smooth experience
nikivi
nikiviOPā€¢2y 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ā€¢2y ago
normally i do ref={ref=>setRef(ref)} here seems you're setting accessor to ref value
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
but this bug is so strange, delete just does this insane cascade thing
thetarnav
thetarnavā€¢2y ago
youre subscribing to todos()
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
oh and i tried to do it as they do in docs
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
well i guess i have signal in my case
thetarnav
thetarnavā€¢2y ago
so it works initially, but not when the target is updated? I'll need to do some experiments here.
nikivi
nikiviOPā€¢2y ago
yes you can clone my repo to replicate
nikivi
nikiviOPā€¢2y ago
GitHub
GitHub - nikitavoloboev/kuskus: Fast todo app
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
it adds the entry but doesn't autofocus first one is ok could be I am using it wrong
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
strange error I did as they have in example i think
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/NewTodo.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
also have type error which is odd as i also have input and stackblitz is input šŸ¤”
thetarnav
thetarnavā€¢2y ago
I've made an update to allow it to be used with ref easier, so you might update
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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ā€¢2y ago
new inputs are created in the demo too so I'm not sure
nikivi
nikiviOPā€¢2y ago
wait i think i need to pass setRef perhaps like in my case its not used
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/NewTodo.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y 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ā€¢2y ago
the demo shows two different methods, you can use either
nikivi
nikiviOPā€¢2y 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ā€¢2y ago
yeah I'm not sure I have to be missing something
nikivi
nikiviOPā€¢2y 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ā€¢2y 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
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y 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ā€¢2y ago
try ref={el => onMount(() => setTimeout(() => el.focus(),200))}
nikivi
nikiviOPā€¢2y ago
nikivi
nikiviOPā€¢2y ago
didn't work šŸ˜¦
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/NewTodo.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y ago
did it like this maybe you meant it differently I have the wildest thing
nikivi
nikiviOPā€¢2y ago
GitHub
kuskus/Page.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
GitHub
kuskus/ActionBar.tsx at main Ā· nikitavoloboev/kuskus
Fast todo app. Contribute to nikitavoloboev/kuskus development by creating an account on GitHub.
nikivi
nikiviOPā€¢2y 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
nikiviOPā€¢2y 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
nikiviOPā€¢2y ago
ok opened an issue, maybe someone knows
thetarnav
thetarnavā€¢2y 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ā€¢2y ago
But this only happens after clicking the plus button. Pressing n works fine
thetarnav
thetarnavā€¢2y 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...

Did you find this page helpful?