As the title says, …
I have a UI that is kind of like a data table, where I type values into cells and hit enter, to create a new row. Once I do, I would like to shift input back to the first cell.
Is there a ways, with the JS module to get live view to behave as described?
I did it with a hook (though I’m not sure it’s the cleanest approach)
<.form
phx-hook="FocusFirstAfterSubmit"
phx-submit={JS.push("create_entry") |> JS.dispatch("submitted", detail: %{id: id})} ...>
const FocusFirstAfterSubmitHook = {
mounted() {
let timeout
this.el.addEventListener('submitted', { detail: { id } }) => {
// clearing existing timeout ensures we don't lose focus if we spam submit
timeout && clearTimeout(timeout)
// the event is received by all forms, not just one, so we must check id
if (detail.id !== this.el.id) { return }
// 200ms timeout allows the form to rerender after submit
timeout = setTimeout(() => {
document.querySelector<HTMLInputElement>(`#${this.el.id}_duration_hours`)?.select()
}, 200)
})
}
}
But I’m unable to find a way to do it via just the JS module
I tried both of these, with and without a target specified
phx-submit={JS.push("create_entry") |> JS.focus()}
phx-submit={JS.push("create_entry") |> JS.focus_first()}
but what seems to happen is, after the form submits, the focus briefly shifts to the first element, and then returns to the one I I’m, as in some step is invalidating it.
I’m probably missing something related to how the components are re-rendered, but I guess I don’t know enough about the internals yet? Any ideas?
Do note that my page has several sections of rows, where each section gets a “new row” form, so is it possible that creates a problem? The fact that the dispatched ‘submitted’ event is received by all such forms makes me thing it’s something like that.
Cheers!